• android Gui系统之SurfaceFlinger(3)---SurfaceFlinger


    7.SurfaceFlinger

    SurfaceFlinger在前面的篇幅了,多有涉及。

    SurfaceFlinger是GUI刷新UI的核心,所以任何关于SurfaceFlinger的改进都会对android UI系统有重大影响。

    SurfaceFlinger主要分为4个部分

    1)黄油计划---project butter

    2)启动过程

    3)SurfaceFlinger & BufferQueue的关系

    4)Vsync信号的处理

    7.1黄油计划

    就是给android系统,图上一层“黄油”。我们来看看andorid是怎么给SurfaceFlinger涂上这层黄油的。

    butter 由2个组成部分,Vsync & Triple buffer。

    Triple buffer:

    上面讲到双缓冲区技术,也提到FrameBufferNativeWindow 在申请buffer的时候,可以是2,或者是3.

    这个3 就是马上要讲到的Triple Buffer技术。

    我们先会过来看看双缓冲技术。

    之前说 双缓冲,是把一个buffer放在bitmap上,等到这个所有元素都准备好以后,在把bitmap刷到屏幕上。

    这样会解决卡顿的感觉。

    我们考虑一种情况,假设屏幕刷新频率是66Hz,CPU频率是100Hz.

    之前已经讲了双缓冲技术,这里简单过一下。

    如上面的假设,UI的刷新是0.015s,而buffer的准备是0.01s

    一个Frame Buffer代表一帧图像。

    0.01s:

    此时,buffer已经准备好数据,而显示器只显示了图像的2/3

    0.015s

    显示器显示了第一帧图像,而buffer已经填充了第二帧的1/3

    0.02s

    Buffer已经准备好了第二帧,而显示器出现了问题,1/3的内容属于第二帧,2/3的内容属于第一帧。

    这就是android引入双缓冲技术的原因。

    如果buffer准备的时间,比屏幕刷新图像的速度慢呢?

    显示屏的每一次刷新,就是对显示器屏幕的扫描,但是它是有间隔的(物理设备嘛,肯定有这个间隔)。

    典型的PC显示器屏幕刷新频率是60Hz,这是因为一秒60帧,从人的角度看,就会觉得很流畅。

    所以间隔1/60秒,也就是16ms 如果我们准备时间<=16ms,那就可以做到“无缝连接”。画面就很流程。

    这段空隙称为VBI。 这个时间就是交换缓冲区最佳的时间。而这个交换的动作就是Vsync 也是SurfaceFlinger的重点。

    如果我们图像准备时间<=16ms. OK,画面是很流畅的,但是我们无法保证设备性能一定很very good。所以也有可能画面准备时间超过16ms

    我们看看这张图。

    刚开始buffer里面有数据A,这时候,可以直接显示在屏幕上。
    过了16ms以后,数据B还没准备好,屏幕只能继续显示A。这样就浪费了依次交换的机会。
    到下一次交换,B被显示在屏幕上。 这里有段时间被浪费了。
    等到下一次A的时候,过了16ms,还是没有准备好,继续浪费。所以双缓冲区技术,也有很大浪费。
    有没有办法规避呢,
    比如上图 B & A之间的这段时间,如果我增加一个buffer,C。
    这样B准备好以后,虽然C没有好,但是B可以显示在屏幕上,等到下一次16ms到了以后,C已经准备好了,这样可以很大程度上减少CPU时间的浪费。
    也就是空间换时间的一种思想。
    所以多缓冲区就是,就是可以根据系统的实际内存情况,来判断buffer的数量。
     

    7.2 SurfaceFlinger的启动

    SurfaceFlinger 我们前面已经说了,它其实就是一个service。

    void SurfaceFlinger::onFirstRef()
    {
        mEventQueue.init(this);
    }

    初始化事件队列。

    void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
    {
        mFlinger = flinger;
        mLooper = new Looper(true);
        mHandler = new Handler(*this);
    }

    创建了looper & Handler

    但是这个looper什么时候起来的呢?

    void MessageQueue::waitMessage() {
        do {
            IPCThreadState::self()->flushCommands();
            int32_t ret = mLooper->pollOnce(-1);
            switch (ret) {
                case Looper::POLL_WAKE:
                case Looper::POLL_CALLBACK:
                    continue;
                case Looper::POLL_ERROR:
                    ALOGE("Looper::POLL_ERROR");
                case Looper::POLL_TIMEOUT:
                    // timeout (should not happen)
                    continue;
                default:
                    // should not happen
                    ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                    continue;
            }
        } while (true);
    }

    可以看到最终会调用looper启动函数。可以看到Looper::POLL_TIMEOUT: android什么都没做,尽管它们不应该发生。

    其实handler兜了一圈,发现最后还是回到surfaceflinger来处理:

    void SurfaceFlinger::onMessageReceived(int32_t what) {
        ATRACE_CALL();
        switch (what) {
            case MessageQueue::TRANSACTION: {
                handleMessageTransaction();
                break;
            }
            case MessageQueue::INVALIDATE: {
                bool refreshNeeded = handleMessageTransaction();
                refreshNeeded |= handleMessageInvalidate();
                refreshNeeded |= mRepaintEverything;
                if (refreshNeeded) {
                    // Signal a refresh if a transaction modified the window state,
                    // a new buffer was latched, or if HWC has requested a full
                    // repaint
                    signalRefresh();
                }
                break;
            }
            case MessageQueue::REFRESH: {
                handleMessageRefresh();
                break;
            }
        }
    }

    7.3 client

    任何有UI界面App都在surfaceflinger里面有client。

    所以是一个app对应一个surfaceflinger里面的client(ISurfaceComposerClient)。

     

     

    下面我们来分析surfaceflinger的2个重要函数:

    sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
    {
        sp<ISurfaceComposerClient> bclient;
        sp<Client> client(new Client(this));
        status_t err = client->initCheck();
        if (err == NO_ERROR) {
            bclient = client;
        }
        return bclient;
    }

    返回ISurfaceComposerClient,也就是client的bind对象实体。

    其实就上面标红的一句,进行必要的有效性检查,现在代码:

    status_t Client::initCheck() const {
        return NO_ERROR;
    }

    有了clinet以后,看下surface的产生。

    status_t Client::createSurface(
            const String8& name,
            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
            sp<IBinder>* handle,
            sp<IGraphicBufferProducer>* gbp)
    {
        /*
         * createSurface must be called from the GL thread so that it can
         * have access to the GL context.
         */
    
        class MessageCreateLayer : public MessageBase {
            SurfaceFlinger* flinger;
            Client* client;
            sp<IBinder>* handle;
            sp<IGraphicBufferProducer>* gbp;
            status_t result;
            const String8& name;
            uint32_t w, h;
            PixelFormat format;
            uint32_t flags;
        public:
            MessageCreateLayer(SurfaceFlinger* flinger,
                    const String8& name, Client* client,
                    uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                    sp<IBinder>* handle,
                    sp<IGraphicBufferProducer>* gbp)
                : flinger(flinger), client(client),
                  handle(handle), gbp(gbp),
                  name(name), w(w), h(h), format(format), flags(flags) {
            }
            status_t getResult() const { return result; }
            virtual bool handler() {
                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->postMessageSync(msg);
        return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
    }

    到来到去,其实就2句话:

    postMessageSync,其实就是一开始不会直接创建surface,然后放入surfaceflinger队列里,这样不会打断现在的操作。

    然后启动createlayer方法。这个方法之前已经分析过了。

    参考:

    《深入理解android内核设计思想》 林学森

     
  • 相关阅读:
    PHP
    PHP
    密码修改机制
    PHP
    PHP
    PHP
    PHP
    Java并发编程:进程和线程的由来(转)
    Java获取文件大小的正确方法(转)
    J2EE开发中常用的缓存策略
  • 原文地址:https://www.cnblogs.com/deman/p/5591846.html
Copyright © 2020-2023  润新知