Display设备管理

2020-01-07  本文已影响0人  泡面先生_Jack

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);
    }
}
上一篇下一篇

猜你喜欢

热点阅读