Android 图形系统(9)---- 硬件合成HWC和DisplayDevice

本文重点介绍 SurfaceFlinger 和 Composer Service 的衔接流程

HWComposer.jpg

HWC2 Composer 的创建

SurfaceFlinger init 函数中,实例化了Hwc2::impl::Composer对象并且将其作为参数构造了 HWComposer 对象

void SurfaceFlinger::init() {
    ...
    getBE().mHwc.reset(
            new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
    getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
    ...
}

HWComposer 类中包含了重要对象:
std::unique_ptr<HWC2::Device> mHwcDevice;
std::vector<DisplayData> mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES};

mHwcDevice 是 HWComposer的重要成员,在构造函数的初始化参数列表中实例化:

HWComposer::HWComposer(std::unique_ptr<android::Hwc2::Composer> composer)
      : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}

HWC2.cpp 中包含了 HWC2::Device,HWC2::Composer,HWC2::Display 三个重要类,HWC2::Device和HWC2::Composer 都只实例化一次,但是 HWC2::Display 可能有多个实例,对应于 primary,external,virtual 多个Display 对象

HWC2::Device 类型的mHwcDevice对象包含了 android::Hwc2::Composer 类型的mComposer对象,android::Hwc2::Composer是一个抽象基类,定义了调用到了Composer HAL Service 的基本接口,SurfaceFlinger 中会实例化的Hwc2::impl::Composer 就继承自android::Hwc2::Composer
Hwc2::impl::Composer 和 android::Hwc2::Composer都定义在 ComposerHal.cpp 中
android::Hwc2::Composer 是一个抽象类,基本接口定义如下:

class Composer {
public:
    virtual Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
                                   std::vector<int>* outReleaseFences) = 0;

    virtual Error presentDisplay(Display display, int* outPresentFence) = 0;

    virtual Error setActiveConfig(Display display, Config config) = 0;

    /*
     * The composer caches client targets internally.  When target is nullptr,
     * the composer uses slot to look up the client target from its cache.
     * When target is not nullptr, the cache is updated with the new target.
     */
    virtual Error setClientTarget(Display display, uint32_t slot, const sp<GraphicBuffer>& target,
                                  int acquireFence, Dataspace dataspace,
                                  const std::vector<IComposerClient::Rect>& damage) = 0;
}

Hwc2::impl::Composer 中继承实现了这些接口,在这些接口中,创建了Composer HAL Service 的client 端,开始和Composer HAL Service 通信

Composer::Composer(const std::string& serviceName) : mWriter(kWriterInitialSize),
      mIsUsingVrComposer(serviceName == std::string("vr"))
{
    ......
    mComposer = V2_1::IComposer::getService(serviceName);

    if (mComposer == nullptr) {
        LOG_ALWAYS_FATAL("failed to get hwcomposer service");
    }

    mComposer->createClient(
            [&](const auto& tmpError, const auto& tmpClient)
            {
                if (tmpError == Error::NONE) {
                    mClient = tmpClient;
                }

}

registerCallback 和 HWC2::Display 对象创建

Composer Service 中提供了registerCallback接口,将函数通过registerCallback注册到 Composer HAL Service,ComposerService 会在Vsync,HotPlug 和 Refresh 事件发生时执行:
registerCallback 提供的接口如下:
HWC2.h

class ComposerCallback {
 public:
    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
                                   Connection connection) = 0;
    virtual void onRefreshReceived(int32_t sequenceId,
                                   hwc2_display_t display) = 0;
    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
                                 int64_t timestamp) = 0;
    virtual ~ComposerCallback() = default;
};

SurfaceFlinger 在init 中,将 this 指针也就是本身注册到了 HWComposer 中,HWComposer 经过mHwcDevice传递到最终是在 HWC2::Device 中实际注册,中间有一个 ComposerCallbackBridge对象的传递,SurfaceFlinger 继承了 HWC::ComposerCallback 类,因此 CallBack 的回调函数实现是在 SurfaceFlinger 中

SurfaceFlinger 中还是会转到 HWComposer 类中做处理,HWComposer 在转回到HWC:Device 中处理,HWC:Device的onHotplug 函数中,会判断Display 的ID 和 Connected 状态是 Connected 还是 Disconnected,创建相应的 Display 对象,保存在std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;

void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
        auto newDisplay = std::make_unique<Display>(
                *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
        newDisplay->setConnected(true);
        mDisplays.emplace(displayId, std::move(newDisplay));
}

注意创建 newDisplay的参数中,将*mComposer.get() 传递了过去,也就是将HWC2::Composer 对象传递了过去保存为 mComposer 成员
这样 HWC2:Display 中 就可以通过mComposer 直接和 ComposerService 进行交互,对于其中 createLayer等接口,返回的 Layer 也有相应的 类HWC::Layer作为一层抽象
HWC2::device 中包含了mDisplays 对象,根据DisplayID 区分,表示可以支持多个Display
std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
此时:
Primary Display,External Display 和 Virtual Display 都可以通过 HWC:Display 实例和 Composer HAL Service 交互

DisplayData

DisplayData 类用于保存 HWC2:Display 和 Composer HAL service 交互时的信息

struct DisplayData {
    DisplayData();
    ~DisplayData();
    void reset();

    bool hasClientComposition;
    bool hasDeviceComposition;
    HWC2::Display* hwcDisplay; // 实际创建的 Display 对象
    HWC2::DisplayRequest displayRequests;
    sp<Fence> lastPresentFence;  // signals when the last set op retires
    std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
    buffer_handle_t outbufHandle;
    sp<Fence> outbufAcquireFence;
    mutable std::unordered_map<int32_t,
            std::shared_ptr<const HWC2::Display::Config>> configMap;

    // protected by mVsyncLock
    HWC2::Vsync vsyncEnabled;

    bool validateWasSkipped;
    HWC2::Error presentError;
};

HWC2::Display* hwcDisplay 保存了HotPlug 处理中创建的 Display 对象,可以直接和Display 对象交互

DisplayDevice

DisplayDevice 是显示设备的抽象,Android 定义了下面三种类型的显示设备:

  • Display Primary: 主显示设备,通常是LCD 显示屏
  • Display External: 扩展显示设备,可以通过 HDMI输出显示内容
  • Display Virtual: 虚拟显示设备,可以通过wifi 等输出画面
    SurfaceFlinger 中 DisplayDevice 负责和 OpenGL-ES 进行交互,SurfaceFlinger 需要将显示的图层设置到HWComposer 对象中,DisplayDevice 与 RenderEngine 交互,通过构造RE::Surface 的方式,使用 GLES RenderEngine 进行合成

DisplayDevice Create 和 prepareFrame 流程:


DisplayDevice.jpg

DisplayDevice 中的重要成员:

Vector< sp<Layer> > mVisibleLayersSortedByZ;  //当前需要显示的所有 Layer 实例
sp<ANativeWindow> mNativeWindow; // Surface 的实例,用于表示用于显示的 Surface
DisplayDevice 的创建
void SurfaceFlinger::processDisplayChangesLocked() {
        for (size_t i = 0; i < cc; i++) {
            sp<DisplaySurface> dispSurface;
            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferProducer> bqProducer;
            sp<IGraphicBufferConsumer> bqConsumer;
            mCreateBufferQueue(&bqProducer, &bqConsumer, false);

            ......
            hwcId = state.type;
            dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
            producer = bqProducer;
        }
        
        if (dispSurface != nullptr) {
        mDisplays.add(display, setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, producer));
        if (!state.isVirtualDisplay()) {
            mEventThread->onHotplugReceived(state.type, true);
        }
        }
                
}

mCreateBufferQueue 是BufferQueue.h 中 createBufferQueue 函数的封装,功能是创建一个Bufferqueue
为Primary Display创建了一个 FramebufferSurface,如果是VirtualDisplay 则会创建 VirtualDisplaySurface;
以FramebufferSurface 作为参数,创建 DisplayDevice,逻辑在 setupNewDisplayDeviceInternal 函数中:

sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
        const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
        const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
     
    auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
    auto nativeWindow = nativeWindowSurface->getNativeWindow();

    ....

    const int displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY ?
        primaryDisplayOrientation : DisplayState::eOrientationDefault;

    // virtual displays are always considered enabled
    auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
                                                                           : HWC_POWER_MODE_OFF;

    sp<DisplayDevice> hw =
            new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
                              dispSurface, std::move(renderSurface), displayWidth, displayHeight,
                              displayInstallOrientation, hasWideColorGamut, hdrCapabilities,
                              supportedPerFrameMetadata, hwcColorModes, initialPowerMode);

}

以传入的Buffqueue producer构造nativeWindowSurface 和 nativeWindow 作为生产者端的 Surface,FramebufferSurface 继承 ConsumerBase 作为消费者端

Framebuffer 的合成

DisplayDevice 调用 swapBuffers,通知 RenderEngine 进行合成,RenderEngine 合成完成后,通过advanceFrame->nextBuffer获取图像数据,然后调用 HWComposer 的 setClientTarget 将FrameBuffer 数据传递给 Composer HAL Service

status_t FramebufferSurface::advanceFrame() {
    uint32_t slot = 0;
    sp<GraphicBuffer> buf;
    sp<Fence> acquireFence(Fence::NO_FENCE);
    Dataspace dataspace = Dataspace::UNKNOWN;
    status_t result = nextBuffer(slot, buf, acquireFence, dataspace);
    mDataSpace = dataspace;
    if (result != NO_ERROR) {
        ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
                strerror(-result), result);
    }
    return result;
}
Framebuffer 的显示

Surfacflinger 的postFramebuffer中,会调用HWComposer 的presentAndGetReleaseFences,通知Composer HAL service 显示所有的 ClientTarget 和 Device Layer

void SurfaceFlinger::postFramebuffer()
    const auto hwcId = displayDevice->getHwcDisplayId();
    if (hwcId >= 0) {
        getBE().mHwc->presentAndGetReleaseFences(hwcId);
    }

}
Frame_present.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容