美文网首页
Display设备管理

Display设备管理

作者: 泡面先生_Jack | 来源:发表于2020-01-07 17:19 被阅读0次

    DisplayDevice介绍

    DisplayDevice描述了一个显示设备,是Android显示设备的抽象类。Android系统中定义了三种Device

            DISPLAY_PRIMARY     = HWC_DISPLAY_PRIMARY,
            DISPLAY_EXTERNAL    = HWC_DISPLAY_EXTERNAL,
            DISPLAY_VIRTUAL     = HWC_DISPLAY_VIRTUAL,
    

    1:DISPLAY_PRIMARY Android 手机主显示屏
    2:DISPLAY_EXTERNAL 一般为外接显示设备
    3:DISPLAY_VIRTUAL 虚拟显示设备,用于WiFi投屏

    第一种类型是基本的设备,基本所有设备都有自带显示屏, 其他两种则需要其他硬件来支持

    SurfaceFlinger中需要显示的图层(layer)将通过DisplayDevice对象传递到OpenGLES中进行合成,因为如果同时有多个显示屏的情况下,不同的Layer可能会显示在不同的屏幕上。合成之后的图像再通过HWComposer对象传递到Framebuffer中显示。DisplayDevice对象中的成员变量mVisibleLayersSortedByZ保存了所有需要显示在本显示设备中显示的Layer对象,同时DisplayDevice对象也保存了和显示设备相关的显示方向、显示区域坐标等信息。
    SurfaceFlinger的init函数中会初始化Display设备,代码如下:

      //先检查硬件设备是否连接,或者是否是主显示屏
      if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
                // All non-virtual displays are currently considered secure.
                bool isSecure = true;
                //给显示设备分配一个Token,并且创建一个DisplayDeviceState对象,保存在SurfaceFlinger的mCurrentState.display列表中
                createBuiltinDisplayLocked(type);
                wp<IBinder> token = mBuiltinDisplays[i];
                
                //为当前设备创建一个Buffer队列,初始化一个生产者和一个消费者,消费者有FrameBufferSurface封装,生产者交由DisplayDevice持有
                sp<IGraphicBufferProducer> producer;
                sp<IGraphicBufferConsumer> consumer;
                BufferQueue::createBufferQueue(&producer, &consumer,
                        new GraphicBufferAlloc());
                //
                sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                        consumer);
                //为甚分配一个ID
                int32_t hwcId = allocateHwcDisplayId(type);
                //根据相关信息,创建DisplayDevice对象
                sp<DisplayDevice> hw = new DisplayDevice(this,
                        type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                        fbs, producer,
                        mRenderEngine->getEGLConfig());
                if (i > DisplayDevice::DISPLAY_PRIMARY) {
                    // FIXME: currently we don't get blank/unblank requests
                    // for displays other than the main display, so we always
                    // assume a connected display is unblanked.
                    ALOGD("marking display %zu as acquired/unblanked", i);
                    hw->setPowerMode(HWC_POWER_MODE_NORMAL);
                }
                //将DiplayDevice保存到SurfaceFlinger的mDisplays中。
                mDisplays.add(token, hw);
            }
        }
    
         getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
    

    1:调用了HWComposer的isConnected来检查显示设备是否已连接,只有连接的硬件设备才会创建对应的DisplayDevice。主设备除外,无论是否连接都会创建一个DisplayDevice。
    2:为当前显示设备创建一个BBinder类型的Token,并且创建一个DisplayDeviceState对象,保存在SurfaceFlinger的mCurrentState.display列表中
    3:为当前显示设备创建一个Buffer队列,初始化一个生产者和一个消费者,消费者有FrameBufferSurface封装,生产者交由DisplayDevice持有
    4:创建DisplayDevice对象,传入Buffer队列的producer,DisplayDevice的构造函数中,会创建一个Surface对象传递给底层的OpenGL ES使用,而这个Surface是一个生产者。在OpenGl ES中合成好了图像之后会将图像数据写到Surface对象中,这将触发consumer对象的onFrameAvailable函数被调用,然后FramebufferSurface调用HWComposer对象mHwc的fbPost函数输出到FB中。
    5:将DiplayDevice保存到SurfaceFlinger的mDisplays中。
    6:调用主显示屏的makeCurrent,绑定DisplayDevice的上下文

    DisplayDevice构造方法如下:

        mNativeWindow = new Surface(producer, false);
        ANativeWindow* const window = mNativeWindow.get();
    
        /*
         * Create our display's surface
         */
    
        EGLSurface surface;
        EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (config == EGL_NO_CONFIG) {
            config = RenderEngine::chooseEglConfig(display, format);
        }
        surface = eglCreateWindowSurface(display, config, window, NULL);
        eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
        eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
    
        if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
            window->setSwapInterval(window, 0);
    
        mConfig = config;
        mDisplay = display;
        mSurface = surface;
        mFormat  = format;
        mPageFlipCount = 0;
        mViewport.makeInvalid();
        mFrame.makeInvalid();
    
        setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
    

    创建OpenGL的EGL环境,我们在前面已经解释过,初始化过后,openGL就可以想Surface中绘制了,绘制完成调用eglswapBuffer来将绘制完成的Buffer发送到Buffer队列,这样FrameBufferSurface就可收到onFrameAvaliable通知了。

    接着看下DisplayDevice的swapBuffer函数

    void DisplayDevice::swapBuffers(HWComposer& hwc) const {
        // 调用eglSwapBuffers()函数的条件:
        //  (1) 没有HWComposer硬件
        //  (2) 这一帧我们需要使用GLES来合成(包括两种情况)
        //    (a) we have framebuffer target support (not present on legacy
        //        devices, where HWComposer::commit() handles things); or
        //    (b) 虚拟显示设备
        if (hwc.initCheck() != NO_ERROR ||
                (hwc.hasGlesComposition(mHwcDisplayId) &&
                 (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
            //调用eglSwapBuffers更新队列
            EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
            ......
        }
    }
    

    swapBuffers用于将Display合成的图像渲染到FB设备的图像缓冲区,一般只有在不支持HWComposer情况下才会调用。
    当DisplayDevice调用swapBuffer函数后,消费者收到onFrameAvailable通知。再来看下FrameBufferSurface的onFrameAvailale函数。

    // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
    void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
        sp<GraphicBuffer> buf;
        sp<Fence> acquireFence;
        //调用NextBuffer从Buffer队列中获取新的Buffer
        status_t err = nextBuffer(buf, acquireFence);
        if (err != NO_ERROR) {
            ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
                    strerror(-err), err);
            return;
        }
        //调用gralloc模块的FB设备的函数fbPost将graphicBuffer图像缓冲区渲染到FB显示缓冲区中.
        err = mHwc.fbPost(mDisplayType, acquireFence, buf);
        if (err != NO_ERROR) {
            ALOGE("error posting framebuffer: %d", err);
        }
    }
    

    相关文章

      网友评论

          本文标题:Display设备管理

          本文链接:https://www.haomeiwen.com/subject/geomoctx.html