SurfaceFlinger旋转流程分析

chipset: MSM8X25Q

codebase: Android4.1

本文主要对SF(SurfaceFilnger)处理旋转事件的流程做个简单分析。GPU和mdp都可以用来旋转,文中对两者穿插说明。

 系统初始化会调用GraphicPlane::setDisplayHardware,此函数主要判断系统是否默认设置了rotation property值,如果有,则先保存下来。另外,SF是以transform其实就是以矩阵来作旋转计算的,计算方法以线性代数中的知识为依据:

void GraphicPlane::setDisplayHardware(DisplayHardware *hw)
{
    mHw = hw;

    // initialize the display orientation transform.
    // it's a constant that should come from the display driver.
    int displayOrientation = ISurfaceComposer::eOrientationDefault;
    char property[PROPERTY_VALUE_MAX];
	/*读取property*/
    if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
        //displayOrientation
        switch (atoi(property)) {
		/*当然,你也可以仿照添加180°的旋转。*/
        case 90:
            displayOrientation = ISurfaceComposer::eOrientation90;
            break;
        case 270:
            displayOrientation = ISurfaceComposer::eOrientation270;
            break;
        }
    }


    const float w = hw->getWidth();
    const float h = hw->getHeight();
	/*根据宽和高以及orientation生成一个transform*/
    GraphicPlane::orientationToTransfrom(displayOrientation, w, h,
            &mDisplayTransform);
	/*90°或者270°时需要变换宽高。*/
    if (displayOrientation & ISurfaceComposer::eOrientationSwapMask) {
        mDisplayWidth = h;
        mDisplayHeight = w;
    } else {
        mDisplayWidth = w;
        mDisplayHeight = h;
    }

	/*保存当前全局旋转角度,意味着整个系统的显示都要根据整个值
来得出最后是否要旋转。如果为90°或者270°,那就是横屏,如果
是180°,画面就要反转180°。*/
    setOrientation(ISurfaceComposer::eOrientationDefault);
}

status_t GraphicPlane::setOrientation(int orientation)
{
    // If the rotation can be handled in hardware, this is where
    // the magic should happen.

    const DisplayHardware& hw(displayHardware());
    const float w = mDisplayWidth;
    const float h = mDisplayHeight;
    mWidth = int(w);
    mHeight = int(h);

    Transform orientationTransform;
    GraphicPlane::orientationToTransfrom(orientation, w, h,
            &orientationTransform);
    if (orientation & ISurfaceComposer::eOrientationSwapMask) {
        mWidth = int(h);
        mHeight = int(w);
    }

    mOrientation = orientation;
	/*将orientation和h/w计算和得出一个全局的transform,这里的
相乘计算方法,就是利用矩阵来实现的。*/
    mGlobalTransform = mDisplayTransform * orientationTransform;
    return NO_ERROR;
}

由于整个系统一直默认旋转只是流程中一个坐标的特殊处理,不管系统上层是否请求旋转,如横屏游戏,sensor坐标变化,默认的旋转是一直会被处理的。

注意别把这两种旋转混淆了,默认旋转是一般情况下用户看到的显示效果,而上层apk

请求的旋转相对默认旋转是瞬间的。

         现在以上层发生旋转事件为例看下SF处理旋转的流程。

 上层调用SurfaceFlinger::setTransactionState设置当前角度变化了:

void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state,
        int orientation, uint32_t flags) {
    Mutex::Autolock _l(mStateLock);

uint32_t transactionFlags = 0;

/*当前坐标和要设置的坐标不相等表明要作旋转了!*/
    if (mCurrentState.orientation != orientation) {
        if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
            mCurrentState.orientation = orientation;
            transactionFlags |= eTransactionNeeded;
        } else if (orientation != eOrientationUnchanged) {
            ALOGW("setTransactionState: ignoring unrecognized orientation: %d",
                    orientation);
        }
    }

	/*设置旋转标志,SF处理的时候会用到。*/
    const size_t count = state.size();
    for (size_t i=0 ; i<count ; i++) {
        const ComposerState& s(state[i]);
        sp<Client> client( static_cast<Client *>(s.client.get()) );
        transactionFlags |= setClientStateLocked(client, s.state);
    }

    if (transactionFlags) {
        // this triggers the transaction
        setTransactionFlags(transactionFlags);

~~snip
}

SF收到消息后,调用SurfaceFlinger::onMessageReceived进行处理,核心的部分都在这里了。

void SurfaceFlinger::onMessageReceived(int32_t what)
{
    ATRACE_CALL();
    switch (what) {
        case MessageQueue::INVALIDATE:
        case MessageQueue::REFRESH: {
//        case MessageQueue::INVALIDATE: {
            // if we're in a global transaction, don't do anything.
            const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
            uint32_t transactionFlags = peekTransactionFlags(mask);
/*处理事务*/
            if (CC_UNLIKELY(transactionFlags)) {
                handleTransaction(transactionFlags);
            }

            const uint32_t mask1 = eDelayedTraversalNeeded;
            uint32_t transactionFlags1 = peekTransactionFlags(mask1);
            if (CC_UNLIKELY(transactionFlags1)) {
                handleDelayedTransaction(transactionFlags);
            }
			/*计算可视区域*/
            // post surfaces (if needed)
            handlePageFlip();

~~snip
      case MessageQueue::REFRESH: {

~~snip
			/*处理几何坐标*/
            if (CC_UNLIKELY(mHwWorkListDirty)) {
                // build the h/w work list
                handleWorkList();
            }
			
			/*render*/
            if (CC_LIKELY(hw.canDraw())) {
                // repaint the framebuffer (if needed)
                handleRepaint();
                // inform the h/w that we're done compositing
                hw.compositionComplete();
                postFramebuffer();
            } else {
                // pretend we did the post
                hw.compositionComplete();
            }

        } break;
    }
}

下面一一对这几个函数分析。

handleTransaction

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
~~snip

    const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
    transactionFlags = getTransactionFlags(mask);
    handleTransactionLocked(transactionFlags);
~~snip
}

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */
	/*判断是否有事务要处理。*/
    const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
    if (layersNeedTransaction) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<LayerBase>& layer = currentLayers[i];
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;
        }
    }
~~snip

if (transactionFlags & eTransactionNeeded) {
		/*有旋转角度变化的事务。*/
        if (mCurrentState.orientation != mDrawingState.orientation) {
            // the orientation has changed, recompute all visible regions
            // and invalidate everything.

            const int dpy = 0;
            const int orientation = mCurrentState.orientation;
            // Currently unused: const uint32_t flags = mCurrentState.orientationFlags;
            GraphicPlane& plane(graphicPlane(dpy));
			/*根据当前旋转的坐标,还有默认的旋转坐标,计算和得出最终全局transform。
此函数前面分析过了。*/
            plane.setOrientation(orientation);
            const Transform& planeTransform(plane.transform());

            // update the shared control block
            const DisplayHardware& hw(plane.displayHardware());
            volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
            dcblk->orientation = orientation;
            dcblk->w = plane.getWidth();
            dcblk->h = plane.getHeight();

			/*旋转过后当然要重新绘制显示画面了,设置标志。*/
            mVisibleRegionsDirty = true;
            mDirtyRegion.set(hw.bounds());
        }

~~snip
}

可见handleTransaction主要设置全局的transform。

 handlePageFlip

void SurfaceFlinger::handlePageFlip()
{
    ATRACE_CALL();
    const DisplayHardware& hw = graphicPlane(0).displayHardware();
    const Region screenRegion(hw.bounds());

    const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
    const bool visibleRegions = lockPageFlip(currentLayers);

        if (visibleRegions || mVisibleRegionsDirty) {
            Region opaqueRegion;
			/*有旋转过,所以要重新计算可视区域*/
            computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
~~snip
}
~~snip

}

void SurfaceFlinger::computeVisibleRegions(
    const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
{
    ATRACE_CALL();

    const GraphicPlane& plane(graphicPlane(0));
    const Transform& planeTransform(plane.transform());
    const DisplayHardware& hw(plane.displayHardware());
    const Region screenRegion(hw.bounds());

    Region aboveOpaqueLayers;
    Region aboveCoveredLayers;
    Region dirty;

    bool secureFrameBuffer = false;

    size_t i = currentLayers.size();
    while (i--) {
        const sp<LayerBase>& layer = currentLayers[i];
		/*将全局的transform传进去,然后调用各个layer作计算。*/
        layer->validateVisibility(planeTransform);
	
      ~~snip
}
}

void LayerBase::validateVisibility(const Transform& planeTransform)
{
const Layer::State& s(drawingState());
/*全局transform和当前layer的transform相乘计算得到一个transform.*/
    const Transform tr(planeTransform * s.transform);
    const bool transformed = tr.transformed();
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t hw_h = hw.getHeight();
    const Rect& crop(s.active.crop);

    Rect win(s.active.w, s.active.h);
    if (!crop.isEmpty()) {
        win.intersect(crop, &win);
    }

mNumVertices = 4;
/* mVertices 相当重要,系统根据当前的transform还有当前layer的
区域作计算,当然也包含了全局的transform信息在里面,计算出来的
坐标保存到了mVertices 去。要注意,mVertices 只是给GPU用的,如果
用mdp做旋转,SF后面的流程会对其做相应设置。*/
    tr.transform(mVertices[0], win.left,  win.top);
    tr.transform(mVertices[1], win.left,  win.bottom);
    tr.transform(mVertices[2], win.right, win.bottom);
    tr.transform(mVertices[3], win.right, win.top);
    for (size_t i=0 ; i<4 ; i++)
        mVertices[i][1] = hw_h - mVertices[i][1];

    if (CC_UNLIKELY(transformed)) {
        // NOTE: here we could also punt if we have too many rectangles
        // in the transparent region
	/*根据transform对透明区域作处理。*/
        if (tr.preserveRects()) {
            // transform the transparent region
            transparentRegionScreen = tr.transform(s.transparentRegion);
        } else {
            // transformation too complex, can't do the transparent region
            // optimization.
            transparentRegionScreen.clear();
        }
    } else {
        transparentRegionScreen = s.transparentRegion;
    }

	/*保存相应的一些信息到新的参数变量中,以便后面用到。*/
    // cache a few things...
    mOrientation = tr.getOrientation();
    mPlaneOrientation = planeTransform.getOrientation();
    mTransform = tr;
    mTransformedBounds = tr.transform(win);
}

可见,从handlePageFlip中,我们主要是得到了GPU要处理的坐标,保存到了mVertices数组中。

 handleWorkList

void SurfaceFlinger::handleWorkList()
{
    mHwWorkListDirty = false;
    HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
        const size_t count = currentLayers.size();
        hwc.createWorkList(count);
        hwc_layer_t* const cur(hwc.getLayers());
        for (size_t i=0 ; cur && i<count ; i++) {
			/*依次调用各个layer的setGeometry 。*/
            currentLayers[i]->setGeometry(&cur[i]);
        }
    }
}

void Layer::setGeometry(hwc_layer_t* hwcl)
{
	/*调用基类函数。*/
    LayerBaseClient::setGeometry(hwcl);

    hwcl->flags &= ~HWC_SKIP_LAYER;

	/*不完全透明时需要GPU处理。*/
    // we can't do alpha-fade with the hwc HAL
    const State& s(drawingState());
    if (s.alpha < 0xFF) {
        hwcl->flags = HWC_SKIP_LAYER;
    }

    /*
     * Transformations are applied in this order:
     * 1) buffer orientation/flip/mirror
     * 2) state transformation (window manager)
     * 3) layer orientation (screen orientation)
     * mTransform is already the composition of (2) and (3)
     * (NOTE: the matrices are multiplied in reverse order)
     */
	
	/*这里就是在根据要求的旋转信息得出最终的transform,
然后赋值给hwcl,hwcl的信息最后会传给mdp处理。*/
    const Transform bufferOrientation(mCurrentTransform);
    hwcl->sourceTransform = bufferOrientation.getOrientation();
    const Transform tr(mTransform * bufferOrientation);

    // this gives us only the "orientation" component of the transform
    const uint32_t finalTransform = tr.getOrientation();

    // we can only handle simple transformation
    if (finalTransform & Transform::ROT_INVALID) {
        hwcl->flags = HWC_SKIP_LAYER;
    } else {
        hwcl->transform = finalTransform;
    }
	/*得到layer区域相对坐标,绝对坐标在基类中计算得到。*/
Rect crop = computeBufferCrop();
	hwcl->sourceCrop.left   = crop.left;
    hwcl->sourceCrop.top    = crop.top;
    hwcl->sourceCrop.right  = crop.right;
    hwcl->sourceCrop.bottom = crop.bottom;
}

由此看来handleWorkList主要是服务于mdp的,如果用GPU旋转的话可以不需要这些信息。

 

handleRepaint

void SurfaceFlinger::handleRepaint()
{
~~snip
setupHardwareComposer();
	/*对各个layer作render*/
    composeSurfaces(mDirtyRegion);

    // update the swap region and clear the dirty region
    mSwapRegion.orSelf(mDirtyRegion);
    mDirtyRegion.clear();
}

void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    HWComposer& hwc(hw.getHwComposer());
    hwc_layer_t* const cur(hwc.getLayers());

    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
    if (!cur || fbLayerCount) {
~~snip
        const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
        const size_t count = layers.size();

        for (size_t i=0 ; i<count ; i++) {
            const sp<LayerBase>& layer(layers[i]);
            const Region clip(dirty.intersect(layer->visibleRegionScreen));
~~snip
		/*如果不是HWC_FRAMEBUFFER 类型的话不处理,也就是让mdp去做处理。*/
#ifdef QCOMHW
                if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER))
                    continue;
#endif
			/*依次调用各种layer的draw函数 */
                // render the layer
                layer->draw(clip);
            }
        }
   ~~snip
}

void LayerBase::draw(const Region& clip) const
{
    //Dont draw External-only layers
    if (isLayerExternalOnly(getLayer())) {
        return;
    }
    onDraw(clip);
}

void Layer::onDraw(const Region& clip) const
{
~~snip
	/*画图*/
    drawWithOpenGL(clip);

    glDisable(GL_TEXTURE_EXTERNAL_OES);
    glDisable(GL_TEXTURE_2D);
}

void LayerBase::drawWithOpenGL(const Region& clip) const
{
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const uint32_t fbHeight = hw.getHeight();
    const State& s(drawingState());

~~snip

    struct TexCoords {
        GLfloat u;
        GLfloat v;
    };

    Rect crop(s.active.w, s.active.h);
    if (!s.active.crop.isEmpty()) {
        crop = s.active.crop;
    }
    GLfloat left = GLfloat(crop.left) / GLfloat(s.active.w);
    GLfloat top = GLfloat(crop.top) / GLfloat(s.active.h);
    GLfloat right = GLfloat(crop.right) / GLfloat(s.active.w);
    GLfloat bottom = GLfloat(crop.bottom) / GLfloat(s.active.h);
	/*得到顶点坐标*/
    TexCoords texCoords[4];
    texCoords[0].u = left;
    texCoords[0].v = top;
    texCoords[1].u = left;
    texCoords[1].v = bottom;
    texCoords[2].u = right;
    texCoords[2].v = bottom;
    texCoords[3].u = right;
    texCoords[3].v = top;
    for (int i = 0; i < 4; i++) {
        texCoords[i].v = 1.0f - texCoords[i].v;
    }

  	/*OpenGL利用下面这些函数将根据纹理坐标和顶点坐标
得到最后layer的显示区域以及内容。*/
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, mVertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glDrawArrays(GL_TRIANGLE_FAN, 0, mNumVertices);

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisable(GL_BLEND);
}

所以,composeSurfaces是服务于GPU的。

虽然mdp已经旋转完成了,但是似乎还没有看到如何送给mdp啊?看看postFramebuffer.

  postFramebuffer

void SurfaceFlinger::postFramebuffer()
{
~~snip

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const nsecs_t now = systemTime();
    mDebugInSwapBuffers = now;
    hw.flip(mSwapRegion);
~~snip
}
void DisplayHardware::flip(const Region& dirty) const
{
~~snip

    if (mHwc->initCheck() == NO_ERROR) {
        mHwc->commit();
    } else {
        eglSwapBuffers(dpy, surface);
    }
~~snip
}

status_t HWComposer::commit() const {
	/*调用了HAL的set,看起来和硬件有关联了!*/
    int err = mHwc->set(mHwc, mDpy, mSur, ((mSwapRectOn)?mListDirty:mList));
    if (mSwapRectOn && mListDirty) {
        mListDirty->flags &= ~HWC_GEOMETRY_CHANGED;
    } else if ( mList) {
        mList->flags &= ~HWC_GEOMETRY_CHANGED;
    }
    return (status_t)err;
}
static int hwc_set(hwc_composer_device_t *dev,
                   hwc_display_t dpy,
                   hwc_surface_t sur,
                   hwc_layer_list_t* list)
{
    int ret = 0;
    hwc_context_t* ctx = (hwc_context_t*)(dev);
    if (LIKELY(list)) {
        VideoOverlay::draw(ctx, list);
        ExtOnly::draw(ctx, list);
        CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
		/*调用到mdp的draw了!!!*/
        MDPComp::draw(ctx, list);
        EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
      ~~snip
}
    return ret;
}

总的下来,流程还是比较清晰的,不过里面很多transform很容易把人给弄晕掉,可以加log看值跟踪下。


2013/02/17




你可能感兴趣的:(SurfaceFlinger旋转流程分析)