Android P 图形显示系统(八) SurfaceFlinger合成流程(三)

本文详细介绍了Android P中SurfaceFlinger的硬件合成过程,包括setUpHWComposer的步骤,如DisplayDevice的配置、工作列表创建、Layer的HWC设置等。在doComposition阶段,讨论了如何进行Client合成,包括GPU的初始化、合成到FBTarget、交换Buffer等。文章深入探讨了SurfaceFlinger在图形显示系统中的关键作用。
摘要由CSDN通过智能技术生成

SurfaceFlinger合成流程(三)

配置硬件合成 setUpHWComposer

回到handleMessageRefresh,继续看Refresh消息的处理。此时需要进行合成显示的数据,在rebuildLayerStacks时,已经被更新到每个Display各自的layersSortedByZ中。Layer栈创建完成后,进行HWC 合成的设置。

setUpHWComposer的代码比较长,我们分段看,在setUpHWComposer中,主要做了以下几件事:

1.DisplayDevice beginFrame

void SurfaceFlinger::setUpHWComposer() {
    ... ...

    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
        bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
        bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;

        //  判断是否需要重新合成
        bool mustRecompose = dirty && !(empty && wasEmpty);

        ... ...

        mDisplays[dpy]->beginFrame(mustRecompose);

        if (mustRecompose) {
            mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
        }
    }

Android对每一块显示屏的处理都是分开的。这里主要是调Display的beginFrame函数。

status_t DisplayDevice::beginFrame(bool mustRecompose) const {
    return mDisplaySurface->beginFrame(mustRecompose);
}

mDisplaySurface根据屏幕有所不同。

主显和外显用的FramebufferSurface,需显示用的VirtualDisplaySurface,我们这里先不关虚显。

status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
    return NO_ERROR;
}

FramebufferSurface在beginFrame是每一做什么过多的处理。

回到setUpHWComposer函数

2.创建工作列表

void SurfaceFlinger::setUpHWComposer() {
     ... ...

    // build the h/w work list
    if (CC_UNLIKELY(mGeometryInvalid)) {
        mGeometryInvalid = false;
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
            const auto hwcId = displayDevice->getHwcDisplayId();
            if (hwcId >= 0) {
                const Vector<sp<Layer>>& currentLayers(
                        displayDevice->getVisibleLayersSortedByZ());
                for (size_t i = 0; i < currentLayers.size(); i++) {
                    const auto& layer = currentLayers[i];
                    if (!layer->hasHwcLayer(hwcId)) {
                        if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
                            layer->forceClientComposition(hwcId);
                            continue;
                        }
                    }

                    layer->setGeometry(displayDevice, i);
                    if (mDebugDisableHWC || mDebugRegion) {
                        layer->forceClientComposition(hwcId);
                    }
                }
            }
        }
    }

对每个Display中的每个Layer创建对应的HWC Layer,注意hwcId,只是对hwcId大于零的Layer才会创建HWC Layer。Layer的createHwcLayer函数如下:

bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
    LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0,
                        "Already have a layer for hwcId %d", hwcId);
    HWC2::Layer* layer = hwc->createLayer(hwcId);
    if (!layer) {
        return false;
    }
    LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId];
    hwcInfo.hwc = hwc;
    hwcInfo.layer = layer;
    layer->setLayerDestroyedListener(
            [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); });
    return true;
}

根据hwcId来创建,也就是说,HWC上层(SurfaceFlinger)的每个Layer,都会为每个Display创建一个HWC Layer。HWComposer 根据hwcId找对HWC2的Display,再通过具体的HWC2::Dispaly去创建自己的HWC Layer;

Layer通过HWComposer来创建,

HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
    if (!isValidDisplay(displayId)) {
        ALOGE("Failed to create layer on invalid display %d", displayId);
        return nullptr;
    }
    auto display = mDisplayData[displayId].hwcDisplay;
    HWC2::Layer* layer;
    auto error = display->createLayer(&layer);
    if (error != HWC2::Error::None) {
        ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
                to_string(error).c_str(), static_cast<int32_t>(error));
        return nullptr;
    }
    return layer;
}

创建HWC Layer的实现,最终是在Vendor实现的HAL中来完成的。对应的HWC2command为HWC2_FUNCTION_CREATE_LAYER

Error HwcHal::createLayer(Display display, Layer* outLayer)
{
    int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
    return static_cast<Error>(err);
}

创建的HWC Layer在HWC2::Dispaly中也保存了一个引用:

* frameworks/native/services/surfaceflinger/DisplayHardware/HWC2.cpp

Error Display::createLayer(Layer** outLayer)
{
    if (!outLayer) {
        return Error::BadParameter;
    }
    hwc2_layer_t layerId = 0;
    auto intError = mComposer.createLayer(mId, &layerId);
    auto error = static_cast<Error>(intError);
    if (error != Error::None) {
        return error;
    }

    auto layer = std::make_unique<Layer>(
            mComposer, mCapabilities, mId, layerId);
    *outLayer = layer.get();
    mLayers.emplace(layerId, std::move(layer));
    return Error::None;
}

如果hwclayer没有创建成功,那么这一层Layer就强制用Client方式合成forceClientComposition。

void Layer::forceClientComposition(int32_t hwcId) {
    if (getBE().mHwcLayers.count(hwcId) == 0) {
        ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
        return;
    }

    getBE().mHwcLayers[hwcId].forceClientComposition = true;
}

另外,如果是Disable掉HWC合成,或者调试Region,也强制用Client方式合成:

mDebugDisableHWC || mDebugRegion

这两个调试方式可以在系统设置,开发者选项中进行设置。

创建完hwcLayer后,设置Layer的几何尺寸:

void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
{
     ... ... //注意,我们这里的数据都是来源于DrawingState
    const State& s(getDrawingState());
    ... ...
    if (!isOpaque(s) || getAlpha() != 1.0f) {
        blendMode =
                mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
    }
    auto error = hwcLayer->setBlendMode(blendMode);

    // 计算displayFrame
    Rect frame{t.transform(computeBounds(activeTransparentRegion))};
    ... ...
    const Transform& tr(displayDevice->getTransform());
    Rect transformedFrame = tr.transform(frame);
    error = hwcLayer->setDisplayFrame(transformedFrame);
    ... ...

    // 计算sourceCrop
    FloatRect sourceCrop = computeCrop(displayDevice);
    error = hwcLayer->setSourceCrop(sourceCrop);
    ... ...

    // 设置Alpha
    float alpha = static_cast<float>(getAlpha());
    error = hwcLayer->setPlaneAlpha(alpha);
    ... ...

    // 设置z-order
    error = hwcLayer->setZOrder(z);
    ... ...

    int type = s.type;
    int appId = s.appId;
    sp<Layer> parent = mDrawingParent.promote();
    if (parent.get()) {
        auto& parentState = parent->getDrawingState();
        type = parentState.type;
        appId = parentState.appId;
    }

    // 设置Layer的信息
    error = hwcLayer->setInfo(type, appId);
    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set info (%d)", mName.string(),
             static_cast<int32_t>(error));

    // 设置transform
    const uint32_t orientation = transform.getOrientation();
    if (orientation & Transform::ROT_INVALID) {
        // we can only handle simple transformation
        hwcInfo.forceClientComposition = true;
    } else {
        auto transform = static_cast<HWC2::Transform>(orientation);
        auto error = hwcLayer->setTransform(transform);
        ... ...
    }
}

注意,我们这里的数据都是来源于DrawingState,setGeometry函数中,主要做了以下几件事:

  • 确认HWCLayer的混合模式
    混合模式,是两个Layer直接的混合方式,主要下面的几种:
/* Blend modes, settable per layer */
typedef enum {
    HWC2_BLEND_MODE_INVALID = 0,

    /* colorOut = colorSrc */
    HWC2_BLEND_MODE_NONE = 1,

    /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */
    HWC2_BLEND_MODE_PREMULTIPLIED = 2,

    /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */
    HWC2_BLEND_MODE_COVERAGE = 3,
} hwc2_blend_mode_t;

HWC2_BLEND_MODE_NONE,不混合,源是什么样,输出就是什么样的。
HWC2_BLEND_MODE_PREMULTIPLIED,预乘,Dst需要做Alpha的处理。
HWC2_BLEND_MODE_COVERAGE,覆盖方式,源和Dst都需要做Alpha的处理。

  • 计算displayFrame并设置给hwcLayer
    displayFrame通过transform转换过的

  • 计算sourceCrop并设置给hwcLayer
    sourceCrop是上层传下来的,再和Dispaly,其他Layer的属性进行计算。

  • 设置Alpha值

  • 设置z-Order

  • 设置Layer的信息
    type和appId是Android Framework层创建SurfaceControl时设置的,可以搜搜"new SurfaceControl"就出来了。type是类型,比如ScreenshotSurfaceBackground等;appId是应用的进程号。

  • 设置变换信息transform

Layer信息的设置,是通过CommandBuffer的读写来完成的,比如,设置混合模式,最终是调的HwcHal的setLayerBlendMode方法。

Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
{
    int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
    return static_cast<Error>(err);
}

回到setUpHWComposer函数

3.设置每层Layer的Frame数据

void SurfaceFlinger::setUpHWComposer() {
     ... ...
    mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();

    // Set the per-frame data
    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
        auto& displayDevice = mDisplays[displayId];
        const auto hwcId = displayDevice->getHwcDisplayId();

        ... ... // 设置每个Dispaly的颜色矩阵
        if (colorMatrix != mPreviousColorMatrix) {
            status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
            ... ...
        }
        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
            if (layer->getForceClientComposition(hwcId)) {
                ALOGV("[%s] Requesting Client composition", layer->getName().string());
                layer->setCompositionType(hwcId, HWC2::Composition::Client);
                continue;
            }

            layer->setPerFrameData(displayDevice);
        }

        if (hasWideColorDisplay) {
            android_color_mode newColorMode;
            android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;

            for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
                newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
                ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
                      layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
                      layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
            }
            newColorMode = pickColorMode(newDataSpace);

            setActiveColorModeInternal(displayDevice, newColorMode);
        }
    }

    mPreviousColorMatrix = colorMatrix;

设置Frame数据时,主要做了以下几件事:

  • 设置每个Dispaly的颜色矩阵
    可以在开发这选项中设置,模拟颜色空间。其支持的transform主要有:
typedef enum {
    HAL_COLOR_TRANSFORM_IDENTITY = 0,
    HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX = 1,
    HAL_COLOR_TRANSFORM_VALUE_INVERSE = 2,
    HAL_COLOR_TRANSFORM_GRAYSCALE = 3,
    HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA = 4,
    HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA = 5,
    HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA = 6,
} android_color_transform_t;

colorTransform主要是用以做颜色变换,以模拟或帮助色盲患者等。

  • 设置每一层Layer的显示数据
    setPerFrameData BufferLayer和ColorLayer的实现不一样。ColorLayer 的逻辑比较简单:
void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
    ... ...
    // 设置可见区域
    auto error = hwcLayer->setVisibleRegion(visible);

    // 制定合成方式
    setCompositionType(hwcId, HWC2::Composition::SolidColor);

    half4 color = getColor();
    // 设置颜色
    error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
                                static_cast<uint8_t>(std::round(255.0f * color.g)),
                                static_cast<uint8_t>(std::round(255.0f *
  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夕月风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值