android Gui系统之SurfaceFlinger(5)

9.Vsync第二部分

在上一篇中我们讲到,视图的刷新需要很多步骤,

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();
    preComposition();  //合成前的准备
    rebuildLayerStacks();//重新建立layer堆栈
    setUpHWComposer();//HWComposer的设定
#ifdef QCOM_BSP
    setUpTiledDr();
#endif
    doDebugFlashRegions();
    doComposition();  //正式合成工作
    postComposition(); //合成的后期工作
}

本文将继续分析这些过程。

9.1 handlerMessageInvalidate

invalidate 字面意思就是使无效,更进一步就是当前的buffer已经无限,请刷新界面。

啥也没干,buffer已经无效,我换下一个,就是handlePageFlip

void SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    handlePageFlip();
}

再来看这个函数:handlePageFlip

bool SurfaceFlinger::handlePageFlip()
{
    Region dirtyRegion;

    bool visibleRegions = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    bool frameQueued = false;

    // Store the set of layers that need updates. This set must not change as
    // buffers are being latched, as this could result in a deadlock.
    // Example: Two producers share the same command stream and:
    // 1.) Layer 0 is latched
    // 2.) Layer 0 gets a new frame
    // 2.) Layer 1 gets a new frame
    // 3.) Layer 1 is latched.
    // Display is now waiting on Layer 1‘s frame, which is behind layer 0‘s
    // second frame. But layer 0‘s second frame could be waiting on display.
    Vector<Layer*> layersWithQueuedFrames;
    for (size_t i = 0, count = layers.size(); i<count ; i++) {
        const sp<Layer>& layer(layers[i]);
        if (layer->hasQueuedFrame()) {
            frameQueued = true;
            if (layer->shouldPresentNow(mPrimaryDispSync)) {
                layersWithQueuedFrames.push_back(layer.get());
            }
        }
    }
    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
        Layer* layer = layersWithQueuedFrames[i];
        const Region dirty(layer->latchBuffer(visibleRegions));
        const Layer::State& s(layer->getDrawingState());
        invalidateLayerStack(s.layerStack, dirty);
    }

    mVisibleRegionsDirty |= visibleRegions;

    // If we will need to wake up at some time in the future to deal with a
    // queued frame that shouldn‘t be displayed during this vsync period, wake
    // up during the next vsync period to check again.
    if (frameQueued && layersWithQueuedFrames.empty()) {
        signalLayerUpdate();
    }

    // Only continue with the refresh if there is actually new work to do
    return !layersWithQueuedFrames.empty();
}

handlePageFlip

@step1:layer->latchBuffer(visibleRegions) 通过该函数锁定各layer的缓冲区。可以理解这个函数一定与BufferQueue有关。

status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
                mFlinger->mPrimaryDispSync);

上面是latchBuffer的核心语句。SurfaceFlingerConsumer前文已经提过,是client端操作bufferqueue的一个端口。所以这个函数一定是操作bufferqueue的。

// Acquire the next buffer.
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    err = acquireBufferLocked(&item, computeExpectedPresent(dispSync));
    if (err != NO_ERROR) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            err = NO_ERROR;
        } else if (err == BufferQueue::PRESENT_LATER) {
            // return the error, without logging
        } else {
            ALOGE("updateTexImage: acquire failed: %s (%d)",
                strerror(-err), err);
        }
        return err;
    }

    // We call the rejecter here, in case the caller has a reason to
    // not accept this buffer.  This is used by SurfaceFlinger to
    // reject buffers which have the wrong size
    int buf = item.mBuf;
    if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
        return NO_ERROR;
    }

    // Release the previous buffer.
    err = updateAndReleaseLocked(item);
    if (err != NO_ERROR) {
        return err;
    }

看了注释,基本解释了大体的过程。

1)  请求新的buffer

2)通过rejecter来判断申请的buffer是否满足surfaceflinger的要求。

3)释放之前的buffer

具体流程可以参考如下:

@step2:SurfaceFlinger:invalidateLayerStack来更新各个区域。

9.2 preComposition 合成前的准备

首先来看2个Vsync Rate相关的代码:

virtual void setVsyncRate(uint32_t count)
virtual void requestNextVsync() 

当count为1时,表示每个信号都要报告,当count =2 时,表示信号 一个间隔一个报告,当count =0时,表示不自动报告,除非主动触发requestNextVsync

void SurfaceFlinger::preComposition()
{
    bool needExtraInvalidate = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        if (layers[i]->onPreComposition()) {
            needExtraInvalidate = true;
        }
    }
    if (needExtraInvalidate) {
        signalLayerUpdate();
    }
}

代码很简单,其实一共就3步,

1)获取全部的layer

2)每个layer onPrecomposition

3) layer update

bool Layer::onPreComposition() {
    mRefreshPending = false;
    return mQueuedFrames > 0 || mSidebandStreamChanged;
}

也就是说,当layer里存放被queue的frame以后,就会出发layer update.

void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue.invalidate();
}

最终会调用:

void EventThread::Connection::requestNextVsync() {
    mEventThread->requestNextVsync(this);
}
void EventThread::requestNextVsync(
        const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    if (connection->count < 0) {
        connection->count = 0;
        mCondition.broadcast();//通知对vsync感兴趣的类
    }
}

那么谁在等待这个broadcast呢?

还是EventThread

void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast();
}

9.3可见区域rebuildlayerStack

void SurfaceFlinger::rebuildLayerStacks() {
#ifdef QCOM_BSP
    char prop[PROPERTY_VALUE_MAX];
    property_get("sys.extended_mode", prop, "0");
    sExtendedMode = atoi(prop) ? true : false;
#endif
    // rebuild the visible layer list per screen
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
        ATRACE_CALL();
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();

        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            Region opaqueRegion;
            Region dirtyRegion;
            Vector< sp<Layer> > layersSortedByZ;
            const sp<DisplayDevice>& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            int dpyId = hw->getHwcDisplayId();
            if (hw->isDisplayOn()) {
                SurfaceFlinger::computeVisibleRegions(dpyId, layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);

                const size_t count = layers.size();
                for (size_t i=0 ; i<count ; i++) {
                    const sp<Layer>& layer(layers[i]);
                    const Layer::State& s(layer->getDrawingState());
                    Region drawRegion(tr.transform(
                            layer->visibleNonTransparentRegion));
                    drawRegion.andSelf(bounds);
                    if (!drawRegion.isEmpty()) {
                        layersSortedByZ.add(layer);
                    }
                }
            }
            hw->setVisibleLayersSortedByZ(layersSortedByZ);
            hw->undefinedRegion.set(bounds);
            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
            hw->dirtyRegion.orSelf(dirtyRegion);
        }
    }
}

rebuildLayerStacks

前文提到mVisibleRegionsDirty这个变量是标记要刷新的可见区域的,我们按字面意思解释下:脏的可见区域,顾名思义,这就是要刷新的区域,因为buffer已经“脏”了。

@step1:系统的display可能不止一个,存在与mDisplays中。

@step2:computeVisibleRegions这个函数根据所有的layer状态,得到2个重要的变量。opaqueRegion & dirtyRegion

dirtyRegion是需要被刷新的。 opaqueRegion 不透明区域,应为layer是按Z-order排序的,左右排在前面的opaqueRegion 会挡住后面的layer。

@step3:Region drawRegion(tr.transform( layer->visibleNonTransparentRegion));程序需要进一步得出每个layer 绘制的区域。

系统的display(显示器)可能不止一个,但是所有的layer都记录在layersSortedByZ里面。记录每个layer属于那个display的变量是 hw->getLayerStack()

@step4:将结果保存到hw中。

这里的不透明区域 是很有意义的一个概念,就是我们在Z-order 上,越靠近用户的时候,值越大,所以是递减操作。

9.4 setUpHWComposer 搭建环境

用于合成surface的功能模块可以有2个,OpenGL ES & HWC,它的管理实在HWC里面实现的。

setUpHWComposer 总的来说就干了3件事情。

1)构造Worklist,并且给DisplayData:list 申请空间

2)填充各layer数据

3)报告HWC(有其他地方决定使用那个)

9.5 doCompostion

关键地方来了,上面的setUpHWComposer 只是交给HWC来负责显示,真正显示的地方就在这里。

1)如何合成

2)如何显示到屏幕上

合成的流程大体如上图。

有了概念后,分析源码:

void SurfaceFlinger::doComposition() {
    ATRACE_CALL();
    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        const sp<DisplayDevice>& hw(mDisplays[dpy]);
        if (hw->isDisplayOn()) {
            // transform the dirty region into this screen‘s coordinate space
            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));

            // repaint the framebuffer (if needed)
            doDisplayComposition(hw, dirtyRegion);

            ++mActiveFrameSequence;

            hw->dirtyRegion.clear();
            hw->flip(hw->swapRegion);
            hw->swapRegion.clear();
        }
        // inform the h/w that we‘re done compositing
        hw->compositionComplete();
    }
    postFramebuffer();
}

变量mRepaintEverything用于说明,是否需要全部重绘所有内容。如果为true的化,那么dirtyRegion就是displaydevice的 width & height构成的RECT。

否则由dirtyRegion转换而来。

doDisplayComposition是每个Display来处理,有可能会用到OpenGL 的接口来交换buffer。

hw->compositionComplete(); 通知HWC合成结束了。

postFramebuffer HWC的Set接口调用。

9.5.1 doDisplayComposition

void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
        const Region& inDirtyRegion)
{
    // We only need to actually compose the display if:
    // 1) It is being handled by hardware composer, which may need this to
    //    keep its virtual display state machine in sync, or
    // 2) There is work to be done (the dirty region isn‘t empty)
    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
    if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
        return;
    }

    Region dirtyRegion(inDirtyRegion);

    // compute the invalid region
    hw->swapRegion.orSelf(dirtyRegion);

    uint32_t flags = hw->getFlags();
    if (flags & DisplayDevice::SWAP_RECTANGLE) {
        // we can redraw only what‘s dirty, but since SWAP_RECTANGLE only
        // takes a rectangle, we must make sure to update that whole
        // rectangle in that case
        dirtyRegion.set(hw->swapRegion.bounds());
    } else {
        if (flags & DisplayDevice::PARTIAL_UPDATES) {
            // We need to redraw the rectangle that will be updated
            // (pushed to the framebuffer).
            // This is needed because PARTIAL_UPDATES only takes one
            // rectangle instead of a region (see DisplayDevice::flip())
            dirtyRegion.set(hw->swapRegion.bounds());
        } else {
            // we need to redraw everything (the whole screen)
            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());
}

doDisplayComposition

传入的参数inDirtyRegion,这就是要刷新的“脏”区域,but,我们的刷新机制,决定了必须是矩形的区域。

So,需要一个最小的矩形,能够包裹inDirtyRegion的区域。

SWAP_RECTANGLE:系统支持软件层面的部分刷新,就需要计算这个最小矩形。

PARTIAL_UPDATES:硬件层面的部分刷新,同理需要这个最小矩形。

最后就是重绘这个区域。

bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
{
    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);

    Region clearRegion;
    bool hasGlesComposition = hwc.hasGlesComposition(id);
    const bool hasHwcComposition = hwc.hasHwcComposition(id);
    if (hasGlesComposition) {
        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
            ALOGW("DisplayDevice::makeCurrent 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("DisplayDevice::makeCurrent on default display failed. Aborting.");
            }
            return false;
        }

        // Never touch the framebuffer if we don‘t have any framebuffer layers
        if (hasHwcComposition) {
            // 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 "clean slate" clear might be more efficient.
            // We‘ll revisit later if needed.
            if(!(mGpuTileRenderEnable && (mDisplays.size()==1)))
                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
#ifdef QCOM_BSP
            clearRegion.clear();
            if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
                clearRegion = region;
                if (cur == end) {
                    drawWormhole(hw, region);
                } else if(mCanUseGpuTileRender) {
                   /* If GPUTileRect DR optimization on clear only the UnionDR
                    * (computed by computeTiledDr) which is the actual region
                    * that will be drawn on FB in this cycle.. */
                    clearRegion = clearRegion.andSelf(Region(mUnionDirtyRect));
                }
            } else
#endif
            {
                if (!region.isEmpty()) {
                    if (cur != end) {
                        if (cur->getCompositionType() != HWC_BLIT)
                            // can happen with SurfaceView
                            drawWormhole(hw, region);
                    } else
                        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());
            }
        }
    }

    /*
     * and then, render the layers targeted at the framebuffer
     */

    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
    const size_t count = layers.size();
    const Transform& tr = hw->getTransform();
    if (cur != end) {
        // we‘re using h/w composer
#ifdef QCOM_BSP
        int fbWidth= hw->getWidth();
        int fbHeight= hw->getHeight();
        /* if GPUTileRender optimization property is on & can be used
         * i) Enable EGL_SWAP_PRESERVED flag
         * ii) do startTile with union DirtyRect
         * else , Disable EGL_SWAP_PRESERVED */
        if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
            if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
                hw->eglSwapPreserved(true);
                Rect dr = mUnionDirtyRect;
                engine.startTileComposition(dr.left, (fbHeight-dr.bottom),
                      (dr.right-dr.left),
                      (dr.bottom-dr.top), 0);
            } else {
                // Un Set EGL_SWAP_PRESERVED flag, if no tiling required.
                hw->eglSwapPreserved(false);
            }
            // DrawWormHole/Any Draw has to be within startTile & EndTile
            if (hasGlesComposition) {
                if (hasHwcComposition) {
                    if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
                        const Rect& scissor(mUnionDirtyRect);
                        engine.setScissor(scissor.left,
                              hw->getHeight()- scissor.bottom,
                              scissor.getWidth(), scissor.getHeight());
                        engine.clearWithColor(0, 0, 0, 0);
                        engine.disableScissor();
                    } else {
                        engine.clearWithColor(0, 0, 0, 0);
                    }
                } else {
                    if (cur->getCompositionType() != HWC_BLIT &&
                          !clearRegion.isEmpty()) {
                        drawWormhole(hw, clearRegion);
                    }
                }
            }
        }
#endif

        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
            const sp<Layer>& layer(layers[i]);
            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                switch (cur->getCompositionType()) {
                    case HWC_CURSOR_OVERLAY:
                    case HWC_OVERLAY: {
                        const Layer::State& state(layer->getDrawingState());
                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
                                && i
                                && layer->isOpaque(state) && (state.alpha == 0xFF)
                                && hasGlesComposition) {
                            // never clear the very first layer since we‘re
                            // guaranteed the FB is already cleared
                            layer->clearWithOpenGL(hw, clip);
                        }
                        break;
                    }
                    case HWC_FRAMEBUFFER: {
                        layer->draw(hw, clip);
                        break;
                    }
                    case HWC_BLIT:
                        //Do nothing
                        break;
                    case HWC_FRAMEBUFFER_TARGET: {
                        // this should not happen as the iterator shouldn‘t
                        // let us get there.
                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
                        break;
                    }
                }
            }
            layer->setAcquireFence(hw, *cur);
        }

#ifdef QCOM_BSP
        // call EndTile, if starTile has been called in this cycle.
        if(mGpuTileRenderEnable && (mDisplays.size()==1)) {
            if(mCanUseGpuTileRender && !mUnionDirtyRect.isEmpty()) {
                engine.endTileComposition(GL_PRESERVE);
            }
        }
#endif
    } else {
        // we‘re not using h/w composer
        for (size_t i=0 ; i<count ; ++i) {
            const sp<Layer>& layer(layers[i]);
            const Region clip(dirty.intersect(
                    tr.transform(layer->visibleRegion)));
            if (!clip.isEmpty()) {
                layer->draw(hw, clip);
            }
        }
    }

    // disable scissor at the end of the frame
    engine.disableScissor();
    return true;
}

doComposeSurfaces

依次分析:hasGlesComposition需要Open GL来合成的layer,hasHwcComposition需要HWC来合成的layer。

这2各变量不是互斥的,有同时存在需要Open GL layer & HWC layer。

hasHwcComposition在2种情况下是true。

1)layer的类型是HWC_Framebuffer的时候,通常情况下是true。

2)cur ==end 核心实现layer->draw 来完成。

3)cur!=end, 将有hwc来实现。

{
    ATRACE_CALL();

    if (CC_UNLIKELY(mActiveBuffer == 0)) {
        // the texture has not been created yet, this Layer has
        // in fact never been drawn into. This happens frequently with
        // SurfaceView because the WindowManager can‘t know when the client
        // has drawn the first time.

        // If there is nothing under us, we paint the screen in black, otherwise
        // we just skip this update.

        // figure out if there is something below us
        Region under;
        const SurfaceFlinger::LayerVector& drawingLayers(
                mFlinger->mDrawingState.layersSortedByZ);
        const size_t count = drawingLayers.size();
        for (size_t i=0 ; i<count ; ++i) {
            const sp<Layer>& layer(drawingLayers[i]);
            if (layer.get() == static_cast<Layer const*>(this))
                break;
            under.orSelf( hw->getTransform().transform(layer->visibleRegion) );
        }
        // if not everything below us is covered, we plug the holes!
        Region holes(clip.subtract(under));
        if (!holes.isEmpty()) {
            clearWithOpenGL(hw, holes, 0, 0, 0, 1);
        }
        return;
    }

    // Bind the current buffer to the GL texture, and wait for it to be
    // ready for us to draw into.
    status_t err = mSurfaceFlingerConsumer->bindTextureImage();
    if (err != NO_ERROR) {
        ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
        // Go ahead and draw the buffer anyway; no matter what we do the screen
        // is probably going to have something visibly wrong.
    }

    bool blackOutLayer = isProtected() || (isSecure() && !hw->isSecure());

    RenderEngine& engine(mFlinger->getRenderEngine());

    if (!blackOutLayer) {
        // TODO: we could be more subtle with isFixedSize()
        const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();

        // Query the texture matrix given our current filtering mode.
        float textureMatrix[16];
        mSurfaceFlingerConsumer->setFilteringEnabled(useFiltering);
        mSurfaceFlingerConsumer->getTransformMatrix(textureMatrix);

        if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {

            /*
             * the code below applies the display‘s inverse transform to the texture transform
             */

            // create a 4x4 transform matrix from the display transform flags
            const mat4 flipH(-1,0,0,0,  0,1,0,0, 0,0,1,0, 1,0,0,1);
            const mat4 flipV( 1,0,0,0, 0,-1,0,0, 0,0,1,0, 0,1,0,1);
            const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);

            mat4 tr;
            uint32_t transform = hw->getOrientationTransform();
            if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
                tr = tr * rot90;
            if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)
                tr = tr * flipH;
            if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V)
                tr = tr * flipV;

            // calculate the inverse
            tr = inverse(tr);

            // and finally apply it to the original texture matrix
            const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
            memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
        }

        // Set things up for texturing.
        mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
        mTexture.setFiltering(useFiltering);
        mTexture.setMatrix(textureMatrix);

        engine.setupLayerTexturing(mTexture);
    } else {
        engine.setupLayerBlackedOut();
    }
    drawWithOpenGL(hw, clip, useIdentityTransform);
    engine.disableTexturing();
}

里面关键就是drawwithOpenGL,可见是由Open GL来合成layer。

  

时间: 2024-12-13 04:25:25

android Gui系统之SurfaceFlinger(5)的相关文章

android Gui系统之SurfaceFlinger(1)

GUI 是任何系统都很重要的一块. android GUI大体分为4大块. 1)SurfaceFlinger 2)WMS 3)View机制 4)InputMethod 这块内容非常之多,但是理解后,可以触类旁通,其实现在主流的系统,包括andorid,ios在构架上,都是有很多相识之处. 我们先来讲SurfaceFlinger 1.OpenGL & OpenGL ES OPenGL ES 是android系统绘画的基础.关于OpenGL部分,可以百度了解下. 先来看一个OpenGL & S

android Gui系统之SurfaceFlinger(1)---SurfaceFlinger概论【转】

转自:https://www.cnblogs.com/deman/p/5584198.html 阅读目录 1.OpenGL & OpenGL ES 2.Android的硬件接口HAL 3.Android显示设备:Gralloc &  FrameBuffer 4.FrameBufferNativeWindow 5.Surface GUI 是任何系统都很重要的一块. android GUI大体分为4大块. 1)SurfaceFlinger 2)WMS 3)View机制 4)InputMetho

图解Android - Android GUI 系统

图解Android - Android GUI 系统 (1) - 概论 图解Android - Android GUI 系统 (2) - 窗口管理系统 图解Android - Android GUI 系统 (3) - Surface Flinger (TBD) 图解Android - Android GUI 系统 (4) - Activity的生命周期 图解Android - Android GUI 系统 (5) - Android的用户输入处理

图解Android - Android GUI 系统 (1) - 概论

http://www.cnblogs.com/samchen2009/p/3364327.html Android的GUI系统是Android最重要也最复杂的系统之一.它包括以下部分: 窗口和图形系统 - Window and View Manager System. 显示合成系统 - Surface Flinger 用户输入系统 - InputManager System 应用框架系统 - Activity Manager System. 它们之间的关系如下图所示 只有对这些系统的功能和工作原

Android GUI系统学习1:Gralloc

Gralloc模块是从Android Eclair(android 2.1)開始增加的一个HAL模块,Gralloc的含义为是Graphics Alloc(图形分配).他对上为libui提供服务,为其分配显存,刷新显示等.对下对framebuffer进行管理. gralloc代码通常位于hardware/libhardware/modules/gralloc文件夹下.包括下面几个文件: Android.mk  framebuffer.cpp  gralloc.cpp  gralloc_priv.

android Gui系统之WMS(2)----窗口的添加

Android系统很多,但是最常用的就两类,一类是有系统进场管理的,系统窗口.还有一类就是由应用程序产生的,应用窗口. 1.系统窗口的添加流程 1.1 addStatusBarWindow PhoneStatus.java中 private void addStatusBarWindow() { makeStatusBarView(); mStatusBarWindowManager = new StatusBarWindowManager(mContext); mStatusBarWindow

Android 显示系统:SurfaceFlinger完全解读

原文地址:https://www.cnblogs.com/blogs-of-lxl/p/11272756.html

10.6 android输入系统_Dispatcher线程_总体框架

图解Android - Android GUI 系统 (5) - Android的Event Input System - 漫天尘沙 - 博客园.htm // 关注里面的Dispatcher处理流程http://www.cnblogs.com/samchen2009/p/3368158.html Dispatcher线程框架: 分发 问:发什么?发给谁? Dispatcher流程如下: 获得事件: (1)放入队列前先稍加处理:分类(Global输入/System输入/User输入).处理紧急事件

Android中GUI系统的Event路由机制

前两天在论坛上看到有人发了一个帖子,询问一个Android GUI Event处理的问题:有一个LinearLayout,里面有很多的child view,他问如何监听这个LinearLayout的Click事件?他的做法是: setClickable(true); setOnClickListener(listener); 最后他发现listener中的回调函数根本不会被调用. 事实上,在Android的GUI系统的中,硬件触发的Event(KeyEvent. TouchEvent. Trac