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

Commit 5f20e2d4 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

reimplement wifi display hack with new external display SF framework

fix a few bugs with external displays

- HWComposer doesn't really handle multiple displays yet
  so there is a lot of ugliness there

- We also need to make sure that external displays are not
  blanked by default

- due to some EGL limitations surfaces being swapped need
  to be current

Change-Id: I82bff05b43bcebd8da863c7c76b4edbc3bc223a9
parent 818b4605
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -140,6 +140,9 @@ void DisplayDevice::init(EGLConfig config)
    mFormat  = format;
    mFormat  = format;
    mPageFlipCount = 0;
    mPageFlipCount = 0;


    // external displays are always considered enabled
    mScreenAcquired = mId >= DisplayDevice::DISPLAY_ID_COUNT;

    // initialize the display orientation transform.
    // initialize the display orientation transform.
    DisplayDevice::setOrientation(DisplayState::eOrientationDefault);
    DisplayDevice::setOrientation(DisplayState::eOrientationDefault);
}
}
+27 −5
Original line number Original line Diff line number Diff line
@@ -334,7 +334,8 @@ void HWComposer::eventControl(int event, int enabled) {
    }
    }
}
}


status_t HWComposer::createWorkList(int32_t id, size_t numLayers) { // FIXME: handle multiple displays
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
    // FIXME: handle multiple displays
    if (uint32_t(id) >= MAX_DISPLAYS)
    if (uint32_t(id) >= MAX_DISPLAYS)
        return BAD_INDEX;
        return BAD_INDEX;


@@ -360,6 +361,15 @@ status_t HWComposer::prepare() const {
    int err = hwcPrepare(mHwc, 1,
    int err = hwcPrepare(mHwc, 1,
            const_cast<hwc_display_contents_1_t**>(mLists));
            const_cast<hwc_display_contents_1_t**>(mLists));
    if (err == NO_ERROR) {
    if (err == NO_ERROR) {

        // here we're just making sure that "skip" layers are set
        // to HWC_FRAMEBUFFER and we're also counting how many layers
        // we have of each type.
        // It would be nice if we could get rid of this entirely, which I
        // think is almost possible.

        // TODO: must handle multiple displays here

        size_t numOVLayers = 0;
        size_t numOVLayers = 0;
        size_t numFBLayers = 0;
        size_t numFBLayers = 0;
        size_t count = getNumLayers(0);
        size_t count = getNumLayers(0);
@@ -397,7 +407,15 @@ status_t HWComposer::prepare() const {
    return (status_t)err;
    return (status_t)err;
}
}


size_t HWComposer::getLayerCount(int32_t id, int type) const { // FIXME: handle multiple displays
size_t HWComposer::getLayerCount(int32_t id, int type) const {
    // FIXME: handle multiple displays
    if (uint32_t(id) >= MAX_DISPLAYS) {
        // FIXME: in practice this is only use to know
        // if we have at least one layer of type.
        return (type == HWC_FRAMEBUFFER) ? 1 : 0;
    }


    switch (type) {
    switch (type) {
        case HWC_OVERLAY:
        case HWC_OVERLAY:
            return mNumOVLayers;
            return mNumOVLayers;
@@ -623,7 +641,11 @@ public:
/*
/*
 * returns an iterator initialized at a given index in the layer list
 * returns an iterator initialized at a given index in the layer list
 */
 */
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) { // FIXME: handle multiple displays
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
    // FIXME: handle multiple displays
    if (uint32_t(id) >= MAX_DISPLAYS)
        return LayerListIterator();

    if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
    if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
        return LayerListIterator();
        return LayerListIterator();
    if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
    if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
@@ -638,14 +660,14 @@ HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t in
/*
/*
 * returns an iterator on the beginning of the layer list
 * returns an iterator on the beginning of the layer list
 */
 */
HWComposer::LayerListIterator HWComposer::begin(int32_t id) { // FIXME: handle multiple displays
HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
    return getLayerIterator(id, 0);
    return getLayerIterator(id, 0);
}
}


/*
/*
 * returns an iterator on the end of the layer list
 * returns an iterator on the end of the layer list
 */
 */
HWComposer::LayerListIterator HWComposer::end(int32_t id) { // FIXME: handle multiple displays
HWComposer::LayerListIterator HWComposer::end(int32_t id) {
    return getLayerIterator(id, getNumLayers(id));
    return getLayerIterator(id, getNumLayers(id));
}
}


+2 −2
Original line number Original line Diff line number Diff line
@@ -426,10 +426,10 @@ void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const


    snprintf(buffer, SIZE,
    snprintf(buffer, SIZE,
            "      "
            "      "
            "z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
            "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
            "isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
            s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
            s.z, s.layerStack, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
            s.active.crop.left, s.active.crop.top,
            s.active.crop.left, s.active.crop.top,
            s.active.crop.right, s.active.crop.bottom,
            s.active.crop.right, s.active.crop.bottom,
            isOpaque(), needsDithering(), contentDirty,
            isOpaque(), needsDithering(), contentDirty,
+55 −74
Original line number Original line Diff line number Diff line
@@ -95,8 +95,7 @@ SurfaceFlinger::SurfaceFlinger()
        mLastSwapBufferTime(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mBootFinished(false)
        mExternalDisplaySurface(EGL_NO_SURFACE)
{
{
    ALOGI("SurfaceFlinger is starting");
    ALOGI("SurfaceFlinger is starting");


@@ -555,38 +554,32 @@ sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
    return mEventThread->createEventConnection();
    return mEventThread->createEventConnection();
}
}


void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture> display) {
void SurfaceFlinger::connectDisplay(const sp<ISurfaceTexture> surface) {
    EGLSurface result = EGL_NO_SURFACE;
    EGLSurface old_surface = EGL_NO_SURFACE;
    sp<SurfaceTextureClient> stc;

    if (display != NULL) {
        stc = new SurfaceTextureClient(display);
        result = eglCreateWindowSurface(mEGLDisplay,
                mEGLConfig, (EGLNativeWindowType)stc.get(), NULL);
        ALOGE_IF(result == EGL_NO_SURFACE,
                "eglCreateWindowSurface failed (ISurfaceTexture=%p)",
                display.get());
    }


    sp<IBinder> token;
    { // scope for the lock
    { // scope for the lock
        Mutex::Autolock _l(mStateLock);
        Mutex::Autolock _l(mStateLock);
        old_surface = mExternalDisplaySurface;
        token = mExtDisplayToken;
        mExternalDisplayNativeWindow = stc;
        mExternalDisplaySurface = result;
        ALOGD("mExternalDisplaySurface = %p", result);
    }
    }


    if (old_surface != EGL_NO_SURFACE) {
    if (token == 0) {
        // Note: EGL allows to destroy an object while its current
        token = createDisplay();
        // it will fail to become current next time though.
        eglDestroySurface(mEGLDisplay, old_surface);
    }
    }
    }


EGLSurface SurfaceFlinger::getExternalDisplaySurface() const {
    { // scope for the lock
        Mutex::Autolock _l(mStateLock);
        Mutex::Autolock _l(mStateLock);
    return mExternalDisplaySurface;
        if (surface == 0) {
            // release our current display. we're guarantee to have
            // a reference to it (token), while we hold the lock
            mExtDisplayToken = 0;
        } else {
            mExtDisplayToken = token;
        }

        DisplayDeviceState& info(mCurrentState.displays.editValueFor(token));
        info.surface = surface;
        setTransactionFlags(eDisplayTransactionNeeded);
    }
}
}


// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -757,49 +750,6 @@ void SurfaceFlinger::handleMessageRefresh() {
    }
    }


    postFramebuffer();
    postFramebuffer();


#if 1
    // render to the external display if we have one
    EGLSurface externalDisplaySurface = getExternalDisplaySurface();
    if (externalDisplaySurface != EGL_NO_SURFACE) {
        EGLSurface cur = eglGetCurrentSurface(EGL_DRAW);
        EGLBoolean success = eglMakeCurrent(eglGetCurrentDisplay(),
                externalDisplaySurface, externalDisplaySurface,
                eglGetCurrentContext());

        ALOGE_IF(!success, "eglMakeCurrent -> external failed");

        if (success) {
            // redraw the screen entirely...
            glDisable(GL_TEXTURE_EXTERNAL_OES);
            glDisable(GL_TEXTURE_2D);
            glClearColor(0,0,0,1);
            glClear(GL_COLOR_BUFFER_BIT);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();

            const sp<DisplayDevice>& hw(getDisplayDevice(0));
            const Vector< sp<LayerBase> >& layers( hw->getVisibleLayersSortedByZ() );
            const size_t count = layers.size();
            for (size_t i=0 ; i<count ; ++i) {
                const sp<LayerBase>& layer(layers[i]);
                layer->draw(hw);
            }

            success = eglSwapBuffers(eglGetCurrentDisplay(), externalDisplaySurface);
            ALOGE_IF(!success, "external display eglSwapBuffers failed");

            hw->compositionComplete();
        }

        success = eglMakeCurrent(eglGetCurrentDisplay(),
                cur, cur, eglGetCurrentContext());

        ALOGE_IF(!success, "eglMakeCurrent -> internal failed");
    }
#endif

}
}


void SurfaceFlinger::postFramebuffer()
void SurfaceFlinger::postFramebuffer()
@@ -830,6 +780,10 @@ void SurfaceFlinger::postFramebuffer()


    if (hwc.initCheck() == NO_ERROR) {
    if (hwc.initCheck() == NO_ERROR) {
        // FIXME: eventually commit() won't take arguments
        // FIXME: eventually commit() won't take arguments
        // FIXME: EGL spec says:
        //   "surface must be bound to the calling thread's current context,
        //    for the current rendering API."
        DisplayDevice::makeCurrent(getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext);
        hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface());
        hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface());
    }
    }


@@ -844,14 +798,22 @@ void SurfaceFlinger::postFramebuffer()
            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
                currentLayers[i]->onLayerDisplayed(hw, &*cur);
                currentLayers[i]->onLayerDisplayed(hw, &*cur);
            }
            }
        } else {
        }

        // FIXME: we need to call eglSwapBuffers() on displays that have
        // GL composition and only on those.
        // however, currently hwc.commit() already does that for the main
        // display and never for the other ones
        if (hw->getDisplayId() >= DisplayDevice::DISPLAY_ID_COUNT) {
            // FIXME: EGL spec says:
            //   "surface must be bound to the calling thread's current context,
            //    for the current rendering API."
            DisplayDevice::makeCurrent(hw, mEGLContext);
            eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
            eglSwapBuffers(mEGLDisplay, hw->getEGLSurface());
            for (size_t i = 0; i < count; i++) {
            for (size_t i = 0; i < count; i++) {
                currentLayers[i]->onLayerDisplayed(hw, NULL);
                currentLayers[i]->onLayerDisplayed(hw, NULL);
            }
            }
        }
        }

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


    mLastSwapBufferTime = systemTime() - now;
    mLastSwapBufferTime = systemTime() - now;
@@ -967,7 +929,6 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
            // (ie: in current state but not in drawing state)
            // (ie: in current state but not in drawing state)
            for (size_t i=0 ; i<cc ; i++) {
            for (size_t i=0 ; i<cc ; i++) {
                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                    // FIXME: we need to pass the surface here
                    const DisplayDeviceState& state(curr[i]);
                    const DisplayDeviceState& state(curr[i]);
                    sp<SurfaceTextureClient> stc(
                    sp<SurfaceTextureClient> stc(
                            new SurfaceTextureClient(state.surface));
                            new SurfaceTextureClient(state.surface));
@@ -1954,6 +1915,26 @@ void SurfaceFlinger::dumpAllLocked(
        layer->shortDump(result, buffer, SIZE);
        layer->shortDump(result, buffer, SIZE);
    }
    }


    /*
     * Dump Display state
     */

    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
        const sp<const DisplayDevice>& hw(mDisplays[dpy]);
        snprintf(buffer, SIZE,
                "+ DisplayDevice[%u]\n"
                "   id=%x, layerStack=%u, (%4dx%4d), orient=%2d, tr=%08x, "
                "flips=%u, secure=%d, numLayers=%u\n",
                dpy,
                hw->getDisplayId(), hw->getLayerStack(),
                hw->getWidth(), hw->getHeight(),
                hw->getOrientation(), hw->getTransform().getType(),
                hw->getPageFlipCount(),
                hw->getSecureLayerVisible(),
                hw->getVisibleLayersSortedByZ().size());
        result.append(buffer);
    }

    /*
    /*
     * Dump SurfaceFlinger global state
     * Dump SurfaceFlinger global state
     */
     */
+1 −3
Original line number Original line Diff line number Diff line
@@ -428,9 +428,7 @@ private:
     * Feature prototyping
     * Feature prototyping
     */
     */


    EGLSurface getExternalDisplaySurface() const;
    sp<IBinder> mExtDisplayToken;
    sp<SurfaceTextureClient> mExternalDisplayNativeWindow;
    EGLSurface mExternalDisplaySurface;
};
};


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