本文重点介绍 SurfaceFlinger 和 Composer Service 的衔接流程
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 中的重要成员:
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);
}
}