Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52bbb1ae authored by Mathias Agopian's avatar Mathias Agopian
Browse files

getting closer to final main composition loop

Change-Id: Icd63782366ffd11d9ea00c925ae5783ed7440cdb
parent 87baae10
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -310,6 +310,14 @@ void DisplayHardware::dump(String8& res) const
    }
}

void DisplayHardware::makeCurrent(const DisplayHardware& hw, EGLContext ctx) {
    EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
    if (sur != hw.mSurface) {
        EGLDisplay dpy = eglGetCurrentDisplay();
        eglMakeCurrent(dpy, hw.mSurface, hw.mSurface, ctx);
    }
}

// ----------------------------------------------------------------------------

void DisplayHardware::setVisibleLayersSortedByZ(const Vector< sp<LayerBase> >& layers) {
+2 −0
Original line number Diff line number Diff line
@@ -107,6 +107,8 @@ public:
    }
    inline Rect bounds() const { return getBounds(); }

    static void makeCurrent(const DisplayHardware& hw, EGLContext ctx);

private:
    void init(EGLConfig config);

+1 −1
Original line number Diff line number Diff line
@@ -294,7 +294,7 @@ void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {

void Layer::setAcquireFence(HWComposer::HWCLayerInterface& layer) {
    int fenceFd = -1;
    if (mNeedHwcFence) {
    if (mNeedHwcFence && (layer.getCompositionType() == HWC_OVERLAY)) {
        sp<Fence> fence = mSurfaceTexture->getCurrentFence();
        if (fence.get()) {
            fenceFd = fence->dup();
+96 −117
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ SurfaceFlinger::SurfaceFlinger()
        mTransactionFlags(0),
        mTransationPending(false),
        mLayersRemoved(false),
        mRepaintEverything(0),
        mBootTime(systemTime()),
        mVisibleRegionsDirty(false),
        mHwWorkListDirty(false),
@@ -577,7 +578,7 @@ void SurfaceFlinger::handleMessageInvalidate() {
void SurfaceFlinger::handleMessageRefresh() {
    handleRefresh();

    if (mVisibleRegionsDirty) {
    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();

@@ -586,9 +587,8 @@ void SurfaceFlinger::handleMessageRefresh() {
         */

        const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
        // TODO: iterate through all displays
        {
            DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
        for (int dpy=0 ; dpy<1 ; dpy++) {  // TODO: iterate through all displays
            DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));

            Region opaqueRegion;
            Region dirtyRegion;
@@ -612,45 +612,70 @@ void SurfaceFlinger::handleMessageRefresh() {
        }
    }

    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        // build the h/w work list
        const bool workListsDirty = mHwWorkListDirty;
        mHwWorkListDirty = false;
        for (int dpy=0 ; dpy<1 ; dpy++) {  // TODO: iterate through all displays
            DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));
            const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
            const size_t count = currentLayers.size();

    // TODO: iterate through all displays
    for (int dpy=0 ; dpy<1 ; dpy++) {
        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(0)));
        if (hw.dirtyRegion.isEmpty()) {
            continue;
            hwc.createWorkList(count); // FIXME: the worklist should include enough space for all layer of all displays

            HWComposer::LayerListIterator cur = hwc.begin();
            const HWComposer::LayerListIterator end = hwc.end();
            for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
                const sp<LayerBase>& layer(currentLayers[i]);

                if (CC_UNLIKELY(workListsDirty)) {
                    layer->setGeometry(hw, *cur);
                    if (mDebugDisableHWC || mDebugRegion) {
                        cur->setSkip(true);
                    }
                }

                /*
                 * update the per-frame h/w composer data for each layer
                 * and build the transparent region of the FB
                 */
                layer->setPerFrameData(*cur);
            }
        }
        status_t err = hwc.prepare();
        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
    }

    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (int dpy=0 ; dpy<1 ; dpy++) {  // TODO: iterate through all displays
        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));

        // transform the dirty region into this screen's coordinate space
        const Transform& planeTransform(hw.getTransform());
        Region dirtyRegion;
        if (repaintEverything) {
            dirtyRegion.set(hw.bounds());
        } else {
            dirtyRegion = planeTransform.transform(hw.dirtyRegion);
            dirtyRegion.andSelf(hw.bounds());
        } else {
            dirtyRegion.set(hw.bounds());
        }
        hw.dirtyRegion.clear();

        // build the h/w work list
        if (CC_UNLIKELY(mHwWorkListDirty)) {
            handleWorkList(hw);
        }

        if (CC_LIKELY(hw.canDraw())) {
        if (!dirtyRegion.isEmpty()) {
            if (hw.canDraw()) {
                // repaint the framebuffer (if needed)
                handleRepaint(hw, dirtyRegion);
            }
        }
        // inform the h/w that we're done compositing
        hw.compositionComplete();
            postFramebuffer();
        } else {
            // pretend we did the post
            hw.compositionComplete();
        }
    }

    postFramebuffer();


#if 0
#if 1
    // render to the external display if we have one
    EGLSurface externalDisplaySurface = getExternalDisplaySurface();
    if (externalDisplaySurface != EGL_NO_SURFACE) {
@@ -670,6 +695,7 @@ void SurfaceFlinger::handleMessageRefresh() {
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            DisplayHardware& hw(const_cast<DisplayDevice&>(getDisplayHardware(0)));
            const Vector< sp<LayerBase> >& layers( hw.getVisibleLayersSortedByZ() );
            const size_t count = layers.size();
            for (size_t i=0 ; i<count ; ++i) {
@@ -695,47 +721,53 @@ void SurfaceFlinger::handleMessageRefresh() {
void SurfaceFlinger::postFramebuffer()
{
    ATRACE_CALL();
    // mSwapRegion can be empty here is some cases, for instance if a hidden
    // or fully transparent window is updating.
    // in that case, we need to flip anyways to not risk a deadlock with
    // h/w composer.

    const DisplayHardware& hw(getDefaultDisplayHardware());
    HWComposer& hwc(getHwComposer());
    const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
    size_t numLayers = layers.size();
    const nsecs_t now = systemTime();
    mDebugInSwapBuffers = now;

    HWComposer& hwc(getHwComposer());

    for (int dpy=0 ; dpy<1 ; dpy++) {  // TODO: iterate through all displays
        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));
        if (hwc.initCheck() == NO_ERROR) {
            const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
            const size_t count = currentLayers.size();
            HWComposer::LayerListIterator cur = hwc.begin();
            const HWComposer::LayerListIterator end = hwc.end();
        for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
            if (cur->getCompositionType() == HWC_OVERLAY) {
                layers[i]->setAcquireFence(*cur);
            } else {
                cur->setAcquireFenceFd(-1);
            }
            for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
                const sp<LayerBase>& layer(currentLayers[i]);
                layer->setAcquireFence(*cur);
            }
        }

        hw.flip(hw.swapRegion);
        hw.swapRegion.clear();
    }

    if (hwc.initCheck() == NO_ERROR) {
        // FIXME: eventually commit() won't take arguments
        hwc.commit(mEGLDisplay, getDefaultDisplayHardware().getEGLSurface());
    }

    for (int dpy=0 ; dpy<1 ; dpy++) {  // TODO: iterate through all displays
        DisplayHardware& hw(const_cast<DisplayHardware&>(getDisplayHardware(dpy)));
        const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        if (hwc.initCheck() == NO_ERROR) {
        hwc.commit(mEGLDisplay, hw.getEGLSurface());
            HWComposer::LayerListIterator cur = hwc.begin();
            const HWComposer::LayerListIterator end = hwc.end();
        for (size_t i = 0; cur != end && i < numLayers; ++i, ++cur) {
            layers[i]->onLayerDisplayed(&*cur);
            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
                currentLayers[i]->onLayerDisplayed(&*cur);
            }
        } else {
            eglSwapBuffers(mEGLDisplay, hw.getEGLSurface());
        for (size_t i = 0; i < numLayers; i++) {
            layers[i]->onLayerDisplayed(NULL);
            for (size_t i = 0; i < count; i++) {
                currentLayers[i]->onLayerDisplayed(NULL);
            }
        }

        // FIXME: we need to call eglSwapBuffers() on displays that have GL composition
    }

    mLastSwapBufferTime = systemTime() - now;
    mDebugInSwapBuffers = 0;
}
@@ -1028,27 +1060,6 @@ void SurfaceFlinger::handleRefresh()
    }
}


void SurfaceFlinger::handleWorkList(const DisplayHardware& hw)
{
    mHwWorkListDirty = false;
    HWComposer& hwc(getHwComposer());
    if (hwc.initCheck() == NO_ERROR) {
        const Vector< sp<LayerBase> >& currentLayers(hw.getVisibleLayersSortedByZ());
        const size_t count = currentLayers.size();
        hwc.createWorkList(count);

        HWComposer::LayerListIterator cur = hwc.begin();
        const HWComposer::LayerListIterator end = hwc.end();
        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
            currentLayers[i]->setGeometry(hw, *cur);
            if (mDebugDisableHWC || mDebugRegion) {
                cur->setSkip(true);
            }
        }
    }
}

void SurfaceFlinger::handleRepaint(const DisplayHardware& hw,
        const Region& inDirtyRegion)
{
@@ -1063,10 +1074,6 @@ void SurfaceFlinger::handleRepaint(const DisplayHardware& hw,
        debugFlashRegions(hw, dirtyRegion);
    }

    // set the frame buffer
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    uint32_t flags = hw.getFlags();
    if (flags & DisplayHardware::SWAP_RECTANGLE) {
        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
@@ -1087,57 +1094,29 @@ void SurfaceFlinger::handleRepaint(const DisplayHardware& hw,
        }
    }

    setupHardwareComposer(hw);
    composeSurfaces(hw, dirtyRegion);

    // update the swap region and clear the dirty region
    hw.swapRegion.orSelf(dirtyRegion);
}

void SurfaceFlinger::setupHardwareComposer(const DisplayHardware& hw)
void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& dirty)
{
    HWComposer& hwc(getHwComposer());
    HWComposer::LayerListIterator cur = hwc.begin();
    const HWComposer::LayerListIterator end = hwc.end();
    if (cur == end) {
        return;
    }

    const Vector< sp<LayerBase> >& layers(hw.getVisibleLayersSortedByZ());
    size_t count = layers.size();

    ALOGE_IF(hwc.getNumLayers() != count,
            "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
            hwc.getNumLayers(), count);

    // just to be extra-safe, use the smallest count
    if (hwc.initCheck() == NO_ERROR) {
        count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
    }
    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);  // FIXME: this should be per display
    if (cur==end || fbLayerCount) {

    /*
     *  update the per-frame h/w composer data for each layer
     *  and build the transparent region of the FB
     */
    for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
        const sp<LayerBase>& layer(layers[i]);
        layer->setPerFrameData(*cur);
    }
    status_t err = hwc.prepare();
    ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
}
        DisplayHardware::makeCurrent(hw, mEGLContext);

void SurfaceFlinger::composeSurfaces(const DisplayHardware& hw, const Region& dirty)
{
    HWComposer& hwc(getHwComposer());
    HWComposer::LayerListIterator cur = hwc.begin();
    const HWComposer::LayerListIterator end = hwc.end();
        // set the frame buffer
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

    const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
    if (cur==end || fbLayerCount) {
        // Never touch the framebuffer if we don't have any framebuffer layers

        if (hwc.getLayerCount(HWC_OVERLAY)) {
        if (hwc.getLayerCount(HWC_OVERLAY)) { // FIXME: this should be per display
            // 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
+0 −2
Original line number Diff line number Diff line
@@ -237,7 +237,6 @@ private:
    void handlePageFlip();

    void handleRefresh();
    void handleWorkList(const DisplayHardware& hw);
    void handleRepaint(const DisplayHardware& hw, const Region& dirtyRegion);

    /* ------------------------------------------------------------------------
@@ -339,7 +338,6 @@ private:
            uint32_t layerStack,
            Region& dirtyRegion, Region& opaqueRegion);
    void postFramebuffer();
    void setupHardwareComposer(const DisplayHardware& hw);
    void composeSurfaces(const DisplayHardware& hw, const Region& dirty);
    void drawWormhole(const Region& region) const;
    GLuint getProtectedTexName() const {