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

Commit cde87a3b authored by Mathias Agopian's avatar Mathias Agopian
Browse files

refactor things a bit

- decouple GL and main display initialization
- ensure that each "supported" display has its own FramebufferSurface
- onScreenAcquired/Released now takes a display

Change-Id: If34a05f3dea40f6c79db77f4dde283a2580daac4
parent c8cff90d
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
@@ -561,22 +561,34 @@ size_t HWComposer::getNumLayers(int32_t id) const {
            mDisplayData[id].list->numHwLayers : 0;
}

int HWComposer::fbPost(buffer_handle_t buffer)
{
int HWComposer::getVisualID() const {
    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
        return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
    } else {
        return mFbDev->format;
    }
}

int HWComposer::fbPost(buffer_handle_t buffer) {
    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
        return mFbDev->post(mFbDev, buffer);
    }
    return NO_ERROR;
}

int HWComposer::fbCompositionComplete()
{
int HWComposer::fbCompositionComplete() {
    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
        if (mFbDev->compositionComplete) {
            return mFbDev->compositionComplete(mFbDev);
        } else {
            return INVALID_OPERATION;
        }
    }
    return NO_ERROR;
}

void HWComposer::fbDump(String8& result) {
    if (mFbDev->common.version >= 1 && mFbDev->dump) {
    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
        const size_t SIZE = 4096;
        char buffer[SIZE];
        mFbDev->dump(mFbDev, buffer, SIZE);
@@ -727,7 +739,7 @@ HWComposer::LayerListIterator HWComposer::end(int32_t id) {
void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
        const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
    if (mHwc) {
        result.append("Hardware Composer state:\n");
        result.appendFormat("Hardware Composer state (version %8x):\n", hwcApiVersion(mHwc));
        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
        for (size_t i=0 ; i<mNumDisplays ; i++) {
            const DisplayData& disp(mDisplayData[i]);
+4 −0
Original line number Diff line number Diff line
@@ -106,6 +106,10 @@ public:
    // needed forward declarations
    class LayerListIterator;

    // return the visual id to be used to find a suitable EGLConfig for
    // *ALL* displays.
    int getVisualID() const;

    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
    int fbPost(buffer_handle_t buffer);
    int fbCompositionComplete();
+94 −48
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>

#include <utils/misc.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>
@@ -243,6 +244,16 @@ status_t SurfaceFlinger::selectConfigForPixelFormat(
    eglGetConfigs(dpy, NULL, 0, &numConfigs);
    EGLConfig* const configs = new EGLConfig[numConfigs];
    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);

    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
        // is supported by the implementation. we can only be in this case
        // if we have HWC 1.1
        *outConfig = configs[0];
        delete [] configs;
        return NO_ERROR;
    }

    for (int i=0 ; i<n ; i++) {
        EGLint nativeVisualId = 0;
        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
@@ -264,6 +275,11 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
    status_t err;
    EGLint attribs[] = {
            EGL_SURFACE_TYPE,           EGL_WINDOW_BIT,
            EGL_RED_SIZE,               8,
            EGL_GREEN_SIZE,             8,
            EGL_BLUE_SIZE,              8,
            // EGL_RECORDABLE_ANDROID must be last so that we can retry
            // without it easily (see below)
            EGL_RECORDABLE_ANDROID,     EGL_TRUE,
            EGL_NONE
    };
@@ -271,7 +287,7 @@ EGLConfig SurfaceFlinger::selectEGLConfig(EGLDisplay display, EGLint nativeVisua
    if (err) {
        // maybe we failed because of EGL_RECORDABLE_ANDROID
        ALOGW("couldn't find an EGLConfig with EGL_RECORDABLE_ANDROID");
        attribs[2] = EGL_NONE;
        attribs[NELEM(attribs) - 3] = EGL_NONE;
        err = selectConfigForPixelFormat(display, attribs, nativeVisualId, &config);
    }
    ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
@@ -297,13 +313,7 @@ EGLContext SurfaceFlinger::createGLContext(EGLDisplay display, EGLConfig config)
    return ctxt;
}

void SurfaceFlinger::initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw) {
    EGLBoolean result = DisplayDevice::makeCurrent(display, hw, mEGLContext);
    if (!result) {
        ALOGE("Couldn't create a working GLES context. check logs. exiting...");
        exit(0);
    }

void SurfaceFlinger::initializeGL(EGLDisplay display) {
    GLExtensions& extensions(GLExtensions::getInstance());
    extensions.initWithGLStrings(
            glGetString(GL_VENDOR),
@@ -375,39 +385,45 @@ status_t SurfaceFlinger::readyToRun()
    mHwc = new HWComposer(this,
            *static_cast<HWComposer::EventHandler *>(this));

    // Initialize the main display
    // create native window to main display
    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc);
    if (fbs == NULL) {
        ALOGE("Display subsystem failed to initialize. check logs. exiting...");
        exit(0);
    }

    sp<SurfaceTextureClient> stc(new SurfaceTextureClient(
            static_cast<sp<ISurfaceTexture> >(fbs->getBufferQueue())));

    // initialize the config and context
    int format;
    ANativeWindow* const anw = stc.get();
    anw->query(anw, NATIVE_WINDOW_FORMAT, &format);
    EGLint format = mHwc->getVisualID();
    mEGLConfig  = selectEGLConfig(mEGLDisplay, format);
    mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);

    // initialize our main display hardware

    // initialize our non-virtual displays
    for (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
        mDefaultDisplays[i] = new BBinder();
        mCurrentState.displays.add(mDefaultDisplays[i],
                DisplayDeviceState((DisplayDevice::DisplayType)i));
                DisplayDeviceState(DisplayDevice::DisplayType(i)));
    }

    // The main display is a bit special and always exists
    //
    // if we didn't add it here, it would be added automatically during the
    // first transaction, however this would also create some difficulties:
    //
    // - there would be a race where a client could call getDisplayInfo(),
    //   for instance before the DisplayDevice is created.
    //
    // - we need a GL context current in a few places, when initializing
    //   OpenGL ES (see below), or creating a layer,
    //   or when a texture is (asynchronously) destroyed, and for that
    //   we need a valid surface, so it's conveniant to use the main display
    //   for that.

    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc);
    sp<SurfaceTextureClient> stc = new SurfaceTextureClient(
                static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
    sp<DisplayDevice> hw = new DisplayDevice(this,
            DisplayDevice::DISPLAY_PRIMARY,
            mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY],
            anw, fbs, mEGLConfig);
            stc, fbs, mEGLConfig);
    mDisplays.add(mDefaultDisplays[DisplayDevice::DISPLAY_PRIMARY], hw);


    //  initialize OpenGL ES
    initializeGL(mEGLDisplay, hw);
    DisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);
    initializeGL(mEGLDisplay);

    // start the EventThread
    mEventThread = new EventThread(this);
@@ -416,6 +432,7 @@ status_t SurfaceFlinger::readyToRun()
    // initialize our drawing state
    mDrawingState = mCurrentState;


    // We're now ready to accept clients...
    mReadyToRunBarrier.open();

@@ -1009,16 +1026,41 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
            for (size_t i=0 ; i<cc ; i++) {
                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                    const DisplayDeviceState& state(curr[i]);

                    sp<FramebufferSurface> fbs;
                    sp<SurfaceTextureClient> stc;
                    if (!state.isVirtualDisplay()) {

                        ALOGE_IF(state.surface!=NULL,
                                "adding a supported display, but rendering "
                                "surface is provided (%p), ignoring it",
                                state.surface.get());

                        // for supported (by hwc) displays we provide our
                        // own rendering surface
                        fbs = new FramebufferSurface(*mHwc);
                        stc = new SurfaceTextureClient(
                                static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));
                    } else {
                        if (state.surface != NULL) {
                        sp<SurfaceTextureClient> stc(
                                new SurfaceTextureClient(state.surface));
                            stc = new SurfaceTextureClient(state.surface);
                        }
                    }

                    const wp<IBinder>& display(curr.keyAt(i));
                        sp<DisplayDevice> disp = new DisplayDevice(this,
                                state.type, display, stc, 0, mEGLConfig);
                        disp->setLayerStack(state.layerStack);
                        disp->setProjection(state.orientation,
                    if (stc != NULL) {
                        sp<DisplayDevice> hw = new DisplayDevice(this,
                                state.type, display, stc, fbs, mEGLConfig);
                        hw->setLayerStack(state.layerStack);
                        hw->setProjection(state.orientation,
                                state.viewport, state.frame);
                        mDisplays.add(display, disp);
                        mDisplays.add(display, hw);
                        if (hw->getDisplayType() < DisplayDevice::NUM_DISPLAY_TYPES) {
                            // notify the system that this display is now up
                            // (note onScreenAcquired() is safe to call from
                            // here because we're in the main thread)
                            onScreenAcquired(hw);
                        }
                    }
                }
            }
@@ -1753,9 +1795,7 @@ void SurfaceFlinger::onInitializeDisplays() {
    d.viewport.makeInvalid();
    displays.add(d);
    setTransactionState(state, displays, 0);

    // XXX: this should init default device to "unblank" and all other devices to "blank"
    onScreenAcquired();
    onScreenAcquired(getDefaultDisplayDevice());
}

void SurfaceFlinger::initializeDisplays() {
@@ -1773,21 +1813,25 @@ void SurfaceFlinger::initializeDisplays() {
}


void SurfaceFlinger::onScreenAcquired() {
void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
    ALOGD("Screen about to return, flinger = %p", this);
    sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // XXX: this should be per DisplayDevice
    getHwComposer().acquire();
    hw->acquireScreen();
    if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
        // FIXME: eventthread only knows about the main display right now
        mEventThread->onScreenAcquired();
    }
    mVisibleRegionsDirty = true;
    repaintEverything();
}

void SurfaceFlinger::onScreenReleased() {
void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
    ALOGD("About to give-up screen, flinger = %p", this);
    sp<const DisplayDevice> hw(getDefaultDisplayDevice()); // XXX: this should be per DisplayDevice
    if (hw->isScreenAcquired()) {
        if (hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
            // FIXME: eventthread only knows about the main display right now
            mEventThread->onScreenReleased();
        }
        hw->releaseScreen();
        getHwComposer().release();
        mVisibleRegionsDirty = true;
@@ -1801,7 +1845,8 @@ void SurfaceFlinger::unblank() {
    public:
        MessageScreenAcquired(SurfaceFlinger* flinger) : flinger(flinger) { }
        virtual bool handler() {
            flinger->onScreenAcquired();
            // FIXME: should this be per-display?
            flinger->onScreenAcquired(flinger->getDefaultDisplayDevice());
            return true;
        }
    };
@@ -1815,7 +1860,8 @@ void SurfaceFlinger::blank() {
    public:
        MessageScreenReleased(SurfaceFlinger* flinger) : flinger(flinger) { }
        virtual bool handler() {
            flinger->onScreenReleased();
            // FIXME: should this be per-display?
            flinger->onScreenReleased(flinger->getDefaultDisplayDevice());
            return true;
        }
    };
+4 −3
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ private:
        DisplayDeviceState(DisplayDevice::DisplayType type);
        bool isValid() const { return type >= 0; }
        bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
        bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
        DisplayDevice::DisplayType type;
        sp<ISurfaceTexture> surface;
        uint32_t layerStack;
@@ -238,9 +239,9 @@ private:
    // called on the main thread in response to initializeDisplays()
    void onInitializeDisplays();
    // called on the main thread in response to blank()
    void onScreenReleased();
    void onScreenReleased(const sp<const DisplayDevice>& hw);
    // called on the main thread in response to unblank()
    void onScreenAcquired();
    void onScreenAcquired(const sp<const DisplayDevice>& hw);

    void handleMessageTransaction();
    void handleMessageInvalidate();
@@ -320,7 +321,7 @@ private:
        EGLint const* attrs, PixelFormat format, EGLConfig* outConfig);
    static EGLConfig selectEGLConfig(EGLDisplay disp, EGLint visualId);
    static EGLContext createGLContext(EGLDisplay disp, EGLConfig config);
    void initializeGL(EGLDisplay display, const sp<DisplayDevice>& hw);
    void initializeGL(EGLDisplay display);
    uint32_t getMaxTextureSize() const;
    uint32_t getMaxViewportDims() const;