Android6.0 图像合成过程详解(二)
doComposition函数
一、doComposition合成图层
doComposition这个函数就是合成所有层的图像
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 void SurfaceFlinger::doComposition() { ATRACE_CALL();
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything); for (size_t dpy=0 ; dpy
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
// repaint the framebuffer (if needed) doDisplayComposition(hw, dirtyRegion);
hw->dirtyRegion.clear(); hw->flip(hw->swapRegion); hw->swapRegion.clear(); }
// inform the h/w that we're done compositing hw->compositionComplete(); }
postFramebuffer(); }
上面函数遍历所有的DisplayDevice然后调用doDisplayComposition函数。然后我们再看看doDisplayComposition函数
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
void SurfaceFlinger::doDisplayComposition(const sp
bool isHwcDisplay = hw->getHwcDisplayId() >= 0; if (!isHwcDisplay && inDirtyRegion.isEmpty()) { return; }
Region dirtyRegion(inDirtyRegion);
//swapRegion设置为需要更新的区域 hw->swapRegion.orSelf(dirtyRegion);
uint32_t flags = hw->getFlags();//获得显示设备支持的更新方式标志
if (flags & DisplayDevice::SWAP_RECTANGLE) {//支持矩阵更新 dirtyRegion.set(hw->swapRegion.bounds()); } else {
if (flags & DisplayDevice::PARTIAL_UPDATES) {//支持部分更新 dirtyRegion.set(hw->swapRegion.bounds()); } else {
//将更新区域调整为整个窗口大小 dirtyRegion.set(hw->bounds()); hw->swapRegion = dirtyRegion; } }
if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) { if (!doComposeSurfaces(hw, dirtyRegion)) return;//合成 } else {
RenderEngine& engine(getRenderEngine()); mat4 colorMatrix = mColorMatrix; if (mDaltonize) {
colorMatrix = colorMatrix * mDaltonizer(); }
mat4 oldMatrix = engine.setupColorTransform(colorMatrix); doComposeSurfaces(hw, dirtyRegion);//合成 engine.setupColorTransform(oldMatrix); }
// update the swap region and clear the dirty region hw->swapRegion.orSelf(dirtyRegion);
// swap buffers (presentation)
hw->swapBuffers(getHwComposer());//使用egl将egl中的合成好的图像,输出到DisplayDevice的mSurface中 }
这个函数设置下需要更新的区域,后面调用doComposeSurfaces函数来合成图层,调用完doComposeSurfaces函数后,如果需要egl合成图像话,在这个函数中合成好。而最后调用swapBuffers只是将egl合成好的图像输出到DisplayDevice的mSurface中。
我们再来看看doComposeSurfaces函数,我们先来看一开始的代码,先判断是否有egl合成,然后再看是否有hwc合成(硬件合成)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
bool SurfaceFlinger::doComposeSurfaces(const sp
RenderEngine& engine(getRenderEngine()); const int32_t id = hw->getHwcDisplayId();
HWComposer& hwc(getHwComposer());
HWComposer::LayerListIterator cur = hwc.begin(id); const HWComposer::LayerListIterator end = hwc.end(id);
bool hasGlesComposition = hwc.hasGlesComposition(id); if (hasGlesComposition) {//是否有egl合成
if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW(\failed. Aborting surface composition for display %s\
hw->getDisplayName().string());
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) { ALOGE(\ }
return false; }
// Never touch the framebuffer if we don't have any framebuffer layers const bool hasHwcComposition = hwc.hasHwcComposition(id); if (hasHwcComposition) {//是否有hwc合成
// when using overlays, we assume a fully transparent framebuffer // NOTE: we could reduce how much we need to clear, for instance // remove where there are opaque FB layers. however, on some // GPUs doing a \ // We'll revisit later if needed. engine.clearWithColor(0, 0, 0, 0); } else {
// we start with the whole screen area const Region bounds(hw->getBounds());
// we remove the scissor part
// we're left with the letterbox region
// (common case is that letterbox ends-up being empty) const Region letterbox(bounds.subtract(hw->getScissor()));
// compute the area to clear
Region region(hw->undefinedRegion.merge(letterbox));
// but limit it to the dirty region region.andSelf(dirty);
// screen is already cleared here if (!region.isEmpty()) {
// can happen with SurfaceView drawWormhole(hw, region); } }
if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) { // just to be on the safe side, we don't set the
// scissor on the main display. It should never be needed
// anyways (though in theory it could since the API allows it). const Rect& bounds(hw->getBounds()); const Rect& scissor(hw->getScissor()); if (scissor != bounds) {
// scissor doesn't match the screen's dimensions, so we // need to clear everything outside of it and enable
// the GL scissor so we don't draw anything where we shouldn't
// enable scissor for this frame
const uint32_t height = hw->getHeight();
engine.setScissor(scissor.left, height - scissor.bottom, scissor.getWidth(), scissor.getHeight()); } } } ......
我们来看hasGlesComposition函数和hasHwcComposition函数,就是看其对应的DisplayData中是否有hasFbComp和hasOvComp。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 bool HWComposer::hasGlesComposition(int32_t id) const {
if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) return true;
return mDisplayData[id].hasFbComp; }
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片 bool HWComposer::hasHwcComposition(int32_t id) const {
if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) return false;
return mDisplayData[id].hasOvComp; }
而这两个值是在prepare中调用Hwc的prepare函数之后赋值的 [cpp] view plain copy 在CODE上查看代码片派生到我的代码片 status_t HWComposer::prepare() { ......
int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
ALOGE_IF(err, \
if (err == NO_ERROR) {
// here we're just making sure that \
// to HWC_FRAMEBUFFER and we're also counting how many layers // we have of each type. //
// If there are no window layers, we treat the display has having FB // composition, because SurfaceFlinger will use GLES to draw the // wormhole region.
for (size_t i=0 ; i for (size_t i=0 ; i //ALOGD(\ // i, l.compositionType, l.handle); if (l.flags & HWC_SKIP_LAYER) { l.compositionType = HWC_FRAMEBUFFER; } if (l.compositionType == HWC_FRAMEBUFFER) { disp.hasFbComp = true;//只要有一个layer是HWC_FRAMEBUFFER } if (l.compositionType == HWC_OVERLAY) { disp.hasOvComp = true;//有一个layer是HWC_OVERLAY } if (l.compositionType == HWC_CURSOR_OVERLAY) { disp.hasOvComp = true;//有一个layer是HWC_CURSOR_OVERLAY } } if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {//layer的数量 有framebufferTarget为1 没有为0 disp.hasFbComp = true; } } else { disp.hasFbComp = true;//没有list } } }