Android 图形系统详解

概述

一个页面(Activity)显示到屏幕上主要经过一下几个流程:
启动 Activity → 创建 Window → WMS 注册 Window → SurfaceFlinger 创建 Surface → 合成 layer → 显示
主要涉及三个进程:App进程、System_server进程、SurfaceFlinger进程

  1. App 进程:负责发起 Surface 创建的请求。同时触发对控件的测量、布局、绘制以及输入事件的派发处理,主要在 ViewRootImpl中 触发( AMS 作用是统一调度所有 App 的 Activity )
  2. System_server 进程:主要是 WindowManagerService,负责接收 App 请求,同时和 SurfaceFlinger 建立连接,向 SF 发起具体请求创建 Surface,并且创建 Surace 的辅助管理类 SurfaceControl(与 window 一一对应)
  3. SurfaceFlinger:为 App 创建具体的 Surface,在 SurfaceFlinger 对应 Layer,然后负责管理、合成所有图层,最终显示在屏幕上
    在这里插入图片描述

应用层可通过两种方式将图像绘制到屏幕上:使用 Canvas 或 OpenGL

  • android.graphics.Canvas 是一个 2D 图形 API,从 4.0 开始通过 OpenGLRenderer 的绘制库实现硬件加速,将Canvas 运算转换为 OpenGL 运算,以便它们可以在 GPU 上执行,提升效率
  • OpenGL ES 直接渲染到 Surface ,Android 在 Android.opengl 软件包中提供了 OpenGL ES 接口
    下图是 view 绘制到 display 展示的整体流程,我们主要看左上角虚线框部分,整体分为 App 进程和系统进程两个部分
    在这里插入图片描述

App 进程

概念解释

  • Activity: 一个 Activity 对应创建一个 Surface,每个 Surface 对应 SurfaceFlinger 中的一个 Layer
  • Window:每个 Activity 包含一个 Window 对象(抽象类,提供绘制窗口的通用API),由 PhoneWindow 实现。是 Activity 和整个 View 系统交互的接口。
  • PhoneWindow: 继承于 Window,是 Window 类的具体实现。该类内部包含了一个 DecorView 对象,该对象是所有应用窗口(Activity 界面)的根 View。把一个 FrameLayout 类,即 DecorView 对象进行一定的包装,将他作为应用窗口的根 View,并提供一组通用的窗口操作接口。
  • DecorView:PhoneWindow setContentView 函数中创建,继承 FrameLayout,是所有应用窗口的根 View。
  • WindowManager :继承 ViewManager ,操作 UI 的接口,具备添加、删除和更新View,具体却委托给了WindowsManagerGlobal来进行实现
  • WindowManagerImpl: 实现了 WindowManager,并持有 WindowManagerGlobal 的对象
  • WindowManagerGlobal:单例模式,每个进程只有一个。持有 ViewRootImpl 的对象
  • ViewRootImpl:所有 View 的根,作为 View 与后台各种服务的桥梁。用户输入系统(接收用户按键,触摸屏输入)、窗口系统(复杂窗口的布局,刷新,动画)、显示合成系统(包括定时器Choreograph, SurfaceFlinger)等
  • Surface:app 层用于绘制的对象在这里插入图片描述

流程分析

在这里插入图片描述

源码分析


ActivityThread.java {
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        ......
        activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
                            r.assistToken, r.shareableActivityToken);
        ......
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    
    public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
                boolean isForward, String reason) {
        ......
        wm.addView(decor, l);
        ......
    }
}

Activity.java {
    private Window mWindow;
    
    final void attach(......){
        ......
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        ......
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        ......
    }
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity);
    }
    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }
}

Window.java {
    private WindowManager mWindowManager;
    public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
            boolean hardwareAccelerated) {
        ......
        mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
        ......
    }
}

PhoneWindow.java {
    private DecorView mDecor;
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        ......
        installDecor();
        ......
    }
    private void installDecor() {
        ......
        mDecor = generateDecor(-1);
        ......
    }
    protected DecorView generateDecor(int featureId) {
        ......
        return new DecorView(context, featureId, this, getAttributes());
    }
}
WindowManagerImpl.java {

    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
    
    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
        return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken);
    }
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        ......
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
    }
}
WindowManagerGlobal.java {

    private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
    
    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow, int userId) {
        ......
        ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
        ......
        root = new ViewRootImpl(view.getContext(), display);
        ......
        mRoots.add(root);
        ......
        root.setView(view, wparams, panelParentView, userId);
        ......
    }
}

ViewRootImpl.java {

    View mView;//DecorView
    
    public final Surface mSurface = new Surface();
    private final SurfaceControl mSurfaceControl = new SurfaceControl();
    
    // 接收显示系统的时间脉冲(垂直同步信号- VSync 信号)
    // 同 Vsync 机制配合,控制同步处理输入(Input)、动画(Animation)、绘制(Draw)三个UI操作
    final Choreographer mChoreographer;
    
    public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
        ......
        mView = view;
        ......
        mWindowSession.addToDisplayAsUser()
        ......
        requestLayout();
        ......
    }
    public void requestLayout() {
        ......
        scheduleTraversals();
        ......
    }
    
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
    
    void scheduleTraversals() {
        ......
        mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
        ......
    }
    void doTraversal() {
        ......
        performTraversals();
        ......
    }
    private void performTraversals() {
        ......
        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
        ......
        performLayout(lp, mWidth, mHeight);
        ......
        performDraw()
        ......
    }
    private boolean performDraw() {
        ......
        draw(fullRedrawNeeded, usingAsyncReport && mSyncBuffer);
        ......
    }
    private boolean draw(boolean fullRedrawNeeded, boolean forceDraw) {
        ......
        drawSoftware(surface, mAttachInfo, xOffset, yOffset,
                        scalingRequired, dirty, surfaceInsets);
        ......
    }
    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
        ......
        canvas = mSurface.lockCanvas(dirty);
        ......
        //DecorView
        mView.draw(canvas);
        ......
        surface.unlockCanvasAndPost(canvas);
    }
}

System 进程

概念解释

  • WindowToken:将同一应用组件(Activity、InputMethod、Wallpaper或者Dream)的窗口组织到一起

  • WindowState:表示一个窗口的所有属性,是 WMS 事实上的窗口
    在这里插入图片描述

  • WindowManagerService:为所有窗口分配 Surface、负责 Surface 的显示顺序(Z序)以及大小尺寸、控制窗口动画,并且还是输入系统的中转站

  • Surface:native 层用于处理窗口的大小位置裁剪等操作

  • SurfaceComposerClient:与 SurfaceFlinger 进行通信,代理对象 mClient,对应 SurfaceFlinger 的 Binder 本地 Client 对象

  • SurfaceControl: app 层 surface 向 native 层提交的 buffer 的控制逻辑

  • BufferQueue:数据的生产者(Surface、BufferQueueProducer)与消费者 (SurfaceFlinger、BufferQueueConsumer)

  • Layer:SurfaceFlinger 进行合成的基本操作单元,当应用创建 Surface 的时候在 SurfaceFlinger 内部创建Layer,因此一个 Surface 对应一个 Layer。

  • SurfaceFlinger:运行在独立进程的 Service, 接收所有 Window 的 Surface 作为输入,根据 Z-Order, 透明度,大小,位置等参数,计算出每个 Surface 在最终合成图像中的位置,然后交由 HWComposer 或 OpenGL 生成最终的显示 Buffer, 然后显示到设备上

对应关系:
Activity -> Window -> DecorView -> ViewRootImpl -> WindowState -> Surface -> Layer 是一一对应的。
在这里插入图片描述

流程分析

在这里插入图片描述

源码分析

SurfaceFlinger 启动

main_surfaceflinger.cpp {
    int main(int, char**) {
        ......
        sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
        ......
        flinger->init();
        ......
        // publish surface flinger
        sp<IServiceManager> sm(defaultServiceManager());
        sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
        ......
        // run surface flinger in this thread
        flinger->run();
    }
}
SurfaceFlinger.cpp {
    void SurfaceFlinger::onFirstRef() {
        ......
        mEventQueue.init(this);
        ......
    }
    void SurfaceFlinger::init(){
        ......
        // 初始化OpenGL 图形库相关配置
        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        ......
        // 创建显示设备的抽象代表,负责和显示设备打交道
        mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this));
        ......
        // app的VSync信号,也就是Systrace中的VSync-app,它最终是发往到choreographer,
        // 主要处理三件事情INPUT、ANIMATION、TRAVERSAL
        // start the EventThread
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app");
        mEventThread = new EventThread(vsyncSrc);
        ......
    }
    void SurfaceFlinger::run() {
        do {
            //运行线程,等待数据
            waitForEvent();
        } while (true);
    }
    void SurfaceFlinger::waitForEvent() {
        mEventQueue.waitMessage();
    }
    // 发送数据
    status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
        nsecs_t reltime, uint32_t /* flags */) {
        status_t res = mEventQueue.postMessage(msg, reltime);
        if (res == NO_ERROR) {
            msg->wait();
        }
        return res;
    }
}
MessageQueue.cpp {
    void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
        mFlinger = flinger;
        mLooper = new Looper(true);
        mHandler = new Handler(*this);
    }
    
    status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime) {
        const Message dummyMessage;
        if (relTime > 0) {
            mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
        } else {
            mLooper->sendMessage(messageHandler, dummyMessage);
        }
        return NO_ERROR;
    }
}

创建 Native 层 Surface 以及 SurfaceFlinger 的 Layer

android_view_Surface.cpp {
    static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong nativeObject, jlong surfaceControlNativeObj) {
        Surface* self(reinterpret_cast<Surface *>(nativeObject));
        sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
        // If the underlying IGBP's are the same, we don't need to do anything.
        if (self != nullptr &&
                IInterface::asBinder(self->getIGraphicBufferProducer()) ==
                IInterface::asBinder(ctrl->getIGraphicBufferProducer())) {
            return nativeObject;
        }
        sp<Surface> surface(ctrl->getSurface());
        if (surface != NULL) {
            surface->incStrong(&sRefBaseOwner);
        }
        return reinterpret_cast<jlong>(surface.get());
    }
}
SurfaceControl.cpp {

    sp<SurfaceComposerClient>   mClient;
    
    sp<Surface> SurfaceControl::getSurface() {
        Mutex::Autolock _l(mLock);
        if (mSurfaceData == nullptr) {
            return generateSurfaceLocked();
        }
        return mSurfaceData;
    }
    
    sp<Surface> SurfaceControl::generateSurfaceLocked() {
        ......
        mBbqChild = mClient->createSurface(String8("bbq-wrapper"), 0, 0, mFormat,
                                           flags, mHandle, {}, &ignore);
        // 当 buffer 入队后会回调 BLASTBufferQueue 的 onFrameAvailable
        mBbq = sp<BLASTBufferQueue>::make("bbq-adapter", mBbqChild, mWidth, mHeight, mFormat);
        // This surface is always consumed by SurfaceFlinger, so the
        // producerControlledByApp value doesn't matter; using false.
        mSurfaceData = mBbq->getSurface(true);
        return mSurfaceData;
    }
}

SurfaceComposerClient.cpp {
    
    sp<ISurfaceComposerClient>  mClient;
    
    sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, DisplayID display,uint32_t w, uint32_t h, PixelFormat format, uint32_t flags) {
        sp<SurfaceControl> result;
        if (mStatus == NO_ERROR) {
            ISurfaceComposerClient::surface_data_t data;
            sp<ISurface> surface = mClient->createSurface(&data, name, display, w, h, format, flags);
            if (surface != 0) {
                result = new SurfaceControl(this, surface, data);
            }
        }
        return result;
    }
}
Client.cpp {
    status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) {
        ......
        class MessageCreateLayer : public MessageBase {
            virtual bool handler() {
                //最后会执行这里 createLayer
                result = flinger->createLayer(name, client, w, h, format, flags,
                        handle, gbp);
                return true;
            }
        }
        sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
                name, this, w, h, format, flags, handle, gbp);
        //这个mFlinger 就是SurfaceFlinger对象
        mFlinger->postMessageSync(msg);
        return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
    }
}
SurfaceFlinger.cpp {
    status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) {
        ......
        sp<Layer> layer;
        ......
        result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer);
        ......
        addClientLayer(client, *handle, *gbp, layer);
        ......
        return result;
    }
    status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer){
        ......
        *outLayer = new Layer(this, client, name, w, h, flags);
        ......
        status_t err = (*outLayer)->setBuffers(w, h, format, flags);
        if (err == NO_ERROR) {
            *handle = (*outLayer)->getHandle();
            *gbp = (*outLayer)->getProducer();
        }
        ......
        return err;
    }
}
Layer.cpp {
    void Layer::onFirstRef() {
        // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
        //创建了生产者和消费者缓冲区,这两个缓冲区将来会存放UI的内容数据
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        ......
        BufferQueue::createBufferQueue(&producer, &consumer);
        mProducer = new MonitoredProducer(producer, mFlinger);
        mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
        ......
        // 这里设置使用 双缓存 还是 三重缓存
        #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
        #warning "disabling triple buffering"
            mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
        #else
            mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
        #endif
        ......
    }
}

绘制

ViewRootImpl.java {
    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
        ......
        canvas = mSurface.lockCanvas(dirty);
        ......
        mView.draw(canvas);
        ......
        surface.unlockCanvasAndPost(canvas);
        ......
    }
}

android_view_Surface.cpp {
    static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
        sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
        ......
        ANativeWindow_Buffer buffer;
        //申请图形 buffer
        status_t err = surface->lock(&buffer, dirtyRectPtr);
        ......
        graphics::Canvas canvas(env, canvasObj);
        canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace()));
        ......
        sp<Surface> lockedSurface(surface);
        lockedSurface->incStrong(&sRefBaseOwner);
        return (jlong) lockedSurface.get();
    }
    static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, jlong nativeObject, jobject canvasObj) {
        sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
        ......
        status_t err = surface->unlockAndPost();
        ......
    }
}
Surface.cpp {

    sp<IGraphicBufferProducer> mGraphicBufferProducer;
    
    status_t Surface::lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds) {
        ......
        status_t err = dequeueBuffer(&out, &fenceFd);
        ......
        if (err == NO_ERROR) {
            ......
            sp<GraphicBuffer> backBuffer(GraphicBuffer::getSelf(out));
            const Rect bounds(backBuffer->width, backBuffer->height);
            ......
        }
    }
    int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
        ......
        status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
                                dqInput.height, dqInput.format,dqInput.usage, &mBufferAge,
                                dqInput.getTimestamps ? &frameTimestamps : nullptr);
        ......
    }
    
    status_t Surface::unlockAndPost() {
        ......
        status_t err = mLockedBuffer->unlockAsync(&fd);
        ......
        err = queueBuffer(mLockedBuffer.get(), fd);
        ......
        return err;
    }
    int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
        ......
        int i = getSlotFromBufferLocked(buffer);
        ......
        status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
        ......
        onBufferQueuedLocked(i, fence, output);
        return err;
    }
}
BufferQueueProducer.cpp {
    status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* outFence,
                                            uint32_t width, uint32_t height, PixelFormat format,
                                            uint64_t usage, uint64_t* outBufferAge,
                                            FrameEventHistoryDelta* outTimestamps) {
        ......
        std::unique_lock<std::mutex> lock(mCore->mMutex);
        ......
        int found = BufferItem::INVALID_BUFFER_SLOT;
        while (found == BufferItem::INVALID_BUFFER_SLOT) {
            //从队列中取出一块已经 releas 的 buffer
            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue, lock, &found);
            if (status != NO_ERROR) {
                return status;
            }
            ......
        }
    }
    status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
        std::unique_lock<std::mutex>& lock, int* found) const {
        ......
        *found = getFreeBufferLocked();
        ......
    }
    int BufferQueueProducer::getFreeBufferLocked() const {
        if (mCore->mFreeBuffers.empty()) {
            return BufferQueueCore::INVALID_BUFFER_SLOT;
        }
        int slot = mCore->mFreeBuffers.front();
        mCore->mFreeBuffers.pop_front();
        return slot;
    }
    
    status_t BufferQueueProducer::queueBuffer(int slot,
        const QueueBufferInput &input, QueueBufferOutput *output) {
        ......
        const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
        Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
        Rect croppedRect(Rect::EMPTY_RECT);
        crop.intersect(bufferRect, &croppedRect);
        ......
        mSlots[slot].mFence = acquireFence;
        mSlots[slot].mBufferState.queue();
        ......
        BufferItem item;
        // 相关数据封装成 BufferItem 并入队
        item.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        ......
        mCore->mQueue.push_back(item);
        ......
        //取出 BufferQueueCore 的回调接口,下面调用这个接口的onFrameAvailable 函数,来通知SurfaceFlinger 进行渲染
        frameAvailableListener = mCore->mConsumerListener;
        ......
        // 回调 BLASTBufferQueue 的 onFrameAvailable
        frameAvailableListener->onFrameAvailable(item);

    }
}
BLASTBufferQueue.cpp {
    void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
        ......
        SurfaceComposerClient::Transaction* prevTransaction = nullptr;
        ......
        if (syncTransactionSet) {
            acquireNextBufferLocked(mSyncTransaction);
            // Only need a commit callback when syncing to ensure the buffer that's synced has been
            // sent to SF
            mSyncTransaction->addTransactionCommittedCallback(transactionCommittedCallbackThunk,
                                                              static_cast<void*>(this));
            ......
            if (mAcquireSingleBuffer) {
                prevCallback = mTransactionReadyCallback;
                prevTransaction = mSyncTransaction;
                ......
            }
        }
        if (prevCallback) {
            prevCallback(prevTransaction);
        }
    }
    void BLASTBufferQueue::acquireNextBufferLocked(const std::optional<SurfaceComposerClient::Transaction*> transaction){
        ......
        status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, 0 , false);
        ......
        t = *transaction;
        ......
        //将提交的 buffer 设置给 SurfaceComposerClient 去进行合成显示
        t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseBufferCallback);
        ......
        mergePendingTransactions(t, bufferItem.mFrameNumber);
        ......
    }
}
BufferQueueConsumer.cpp {
    status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
        nsecs_t expectedPresent, uint64_t maxFrameNumber) {
        while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
            ......
            const BufferItem& bufferItem(mCore->mQueue[1]);
            ......
        }
        ......
        //填充相关数据
        outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
        ......
        //通知消费者该buffer可以重新使用了
        listener->onBufferReleased();
    }
}
  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值