android屏幕旋转显示流程

PAD默认屏幕显示方向是竖着显示,改成默认横屏显示需要将屏幕的默认显示方向顺时针旋转90度.

android显示系统的核心是surfaceflinger,它为所有的应用程序提供显示服务,它能够将各种应用程序的2D,3D surface进行组合,合并最终得到的一个main surface数据送入framebuffer,显示的翻转和旋转也是由surfaceflinger完成的,我们大致分析下surfaceflinger的旋转流程:

1.surfaceflinger启动后首先进行初始化操作,设置surfaceflinger的相关属性并创建了DisplayDevice对象

void SurfaceFlinger::init() {
...
#ifdef MTK_AOSP_ENHANCEMENT
    // make sure 3D init success
    if (mEGLContext == EGL_NO_CONTEXT)
    {
        ALOGE("FATAL: couldn't create EGLContext");
        delete mHwc;
        eglTerminate(mEGLDisplay);
        exit(0);
    }

    // init properties setting first
    setMTKProperties();   //设置MTK相关属性
#else
    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");
#endif
...
    // initialize our non-virtual displays
    for (size_t i=0 ; iisConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp token = mBuiltinDisplays[i];


            sp producer;
            sp consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());


            sp fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp hw = new DisplayDevice(this,  //初始化各个DisplayDevice对象
                    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);
            }
            mDisplays.add(token, hw);
        }
    }
}

setMTKProperties()中会设置surfaceflinger的相关属性:

void SurfaceFlinger::setMTKProperties(String8 &result) {
...
    // get info for panel physical rotation
    property_get("ro.sf.hwrotation", value, "0");
    sPropertiesState.mHwRotation = atoi(value);
    snprintf(buffer, sizeof(buffer), "    ro.sf.hwrotation (mHwRotation): %d\n", sPropertiesState.mHwRotation);
    result.append(buffer);
...
}
此处会读取 ro.sf.hwrotation系统属性,这个系统属性决定了显示屏的初始旋转方向,并保存到全局变量sPropertiesState.mHwRotation中

2.DisplayDevice中会调用显示的旋转函数setProjection()

DisplayDevice::DisplayDevice(
        const sp& flinger,
        DisplayType type,
        int32_t hwcId,
        int format,
        bool isSecure,
        const wp& displayToken,
        const sp& displaySurface,
        const sp& producer,
        EGLConfig config)(
...
#ifdef MTK_AOSP_ENHANCEMENT
    mHwOrientation = DisplayState::eOrientationDefault;   //读取默认的显示屏方向


    // Name the display.  The name will be replaced shortly if the display
    // was created with createDisplay().
    switch (mType) {
        case DISPLAY_PRIMARY:
            mDisplayName = "Built-in Screen";
#ifdef MTK_AOSP_ENHANCEMENT
            switch (mFlinger->sPropertiesState.mHwRotation) {     //读取显示屏初始旋转方向
                case 90:
                    mHwOrientation = DisplayState::eOrientation90;
                    break;
                case 180:
                    mHwOrientation = DisplayState::eOrientation180;
                    break;
                case 270:
                    mHwOrientation = DisplayState::eOrientation270;
                    break;
            }
#endif
            break;
        case DISPLAY_EXTERNAL:
            mDisplayName = "HDMI Screen";
            break;
        default:
            mDisplayName = "Virtual Screen";    // e.g. Overlay #n
            break;
    }

    // initialize the display orientation transform.
    setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);  //设置显示屏初始旋转方向
}

void DisplayDevice::setProjection(int orientation,
        const Rect& newViewport, const Rect& newFrame) {
    Rect viewport(newViewport);
    Rect frame(newFrame);

    const int w = mDisplayWidth;
    const int h = mDisplayHeight;

    Transform R;
    DisplayDevice::orientationToTransfrom(orientation, w, h, &R);

    if (!frame.isValid()) {
        // the destination frame can be invalid if it has never been set,
        // in that case we assume the whole display frame.
        frame = Rect(w, h);
    }

    if (viewport.isEmpty()) {
        // viewport can be invalid if it has never been set, in that case
        // we assume the whole display size.
        // it's also invalid to have an empty viewport, so we handle that
        // case in the same way.
        viewport = Rect(w, h);
        if (R.getOrientation() & Transform::ROT_90) {
            // viewport is always specified in the logical orientation
            // of the display (ie: post-rotation).
            swap(viewport.right, viewport.bottom);
        }
    }

    dirtyRegion.set(getBounds());


#ifdef MTK_AOSP_ENHANCEMENT
    // for boot animation black screen issue
    if ((false == mFlinger->getBootFinished()) && (DISPLAY_PRIMARY == mType)) {
        ALOGI("[%s] clear DisplayDevice(type:%d) dirty region while booting",
            __FUNCTION__, mType);

        dirtyRegion.clear();
    }
#endif

    Transform TL, TP, S;
    float src_width  = viewport.width();
    float src_height = viewport.height();
    float dst_width  = frame.width();
    float dst_height = frame.height();
    if (src_width != dst_width || src_height != dst_height) {
        float sx = dst_width  / src_width;
        float sy = dst_height / src_height;
        S.set(sx, 0, 0, sy);
    }

    float src_x = viewport.left;
    float src_y = viewport.top;
    float dst_x = frame.left;
    float dst_y = frame.top;
    TL.set(-src_x, -src_y);
    TP.set(dst_x, dst_y);

#ifdef MTK_AOSP_ENHANCEMENT
    // need to take care of HW rotation for mGlobalTransform
    // for case if the panel is not installed align with device orientation
    if (DisplayState::eOrientationDefault != mHwOrientation) {    
        DisplayDevice::orientationToTransfrom(
            (orientation + mHwOrientation) % (DisplayState::eOrientation270 + 1),
            w, h, &R);
    }
#endif

    // The viewport and frame are both in the logical orientation.
    // Apply the logical translation, scale to physical size, apply the
    // physical translation and finally rotate to the physical orientation.
    mGlobalTransform = R * TP * S * TL;

    const uint8_t type = mGlobalTransform.getType();
    mNeedsFiltering = (!mGlobalTransform.preserveRects() ||
            (type >= Transform::SCALE));

    mScissor = mGlobalTransform.transform(viewport);
    if (mScissor.isEmpty()) {
        mScissor = getBounds();
    }

    mOrientation = orientation;
    mViewport = viewport;
    mFrame = frame;
}

接着调用DisplayDevice类的orientationToTransfrom()方法构造成一个变换矩阵R,然后得到mGlobalTransform这个全局变换矩阵,最后通过mGlobalTransform.transform()这个方法进行显示的旋转

status_t DisplayDevice::orientationToTransfrom(
        int orientation, int w, int h, Transform* tr)
{
    uint32_t flags = 0;
    switch (orientation) {
    case DisplayState::eOrientationDefault:
        flags = Transform::ROT_0;
        break;
    case DisplayState::eOrientation90:
        flags = Transform::ROT_90;
        break;
    case DisplayState::eOrientation180:
        flags = Transform::ROT_180;
        break;
    case DisplayState::eOrientation270:
        flags = Transform::ROT_270;
        break;
    default:
        return BAD_VALUE;
    }
    tr->set(flags, w, h);
    return NO_ERROR;
}

这里调用Transform::set()方法设置矩阵,有兴趣可以深入分析


你可能感兴趣的:(android屏幕旋转显示流程)