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

Commit a8dd5ccf authored by Manoj Kumar AVM's avatar Manoj Kumar AVM Committed by Steve Kondik
Browse files

sf: Determine if virtual display can use HWC for composition

For HWC virtual display using V4L2 approach:
1. HWC virtual display implementation doesn't send output buffer
   back to Surface Flinger.
2. For non-wfd virtual displays(e.g. Simulated Secondary Displays,
   Screen Record, CTS etc..), configure VDS to use GPU for
   composition on output/sink buffer.
3. For wfd virtual display (a.k.a hybrid wfd), use
   Framebuffer surface (similar to external display mechanism).

For HWC virtual display using VDS approach:
1. HWC is allocated for first virtual display connection.
2. Subsequent virtual display sessions will be composed by GLES driver.
ToDo: Modify VDS component to allocate hwcDisplayId based on
mForceHwcCopy (which is based on Usage Flags)

Change-Id: Ib7d2c00ca5fa07908b2eac8085654f8d2cd9af0b
parent 5f97b088
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -88,7 +88,8 @@ HWComposer::HWComposer(
      mFbDev(0), mHwc(0), mNumDisplays(1),
      mCBContext(new cb_context),
      mEventHandler(handler),
      mDebugForceFakeVSync(false)
      mDebugForceFakeVSync(false),
      mVDSEnabled(false)
{
    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
        mLists[i] = 0;
@@ -186,6 +187,15 @@ HWComposer::HWComposer(
        }
    }

    // read system property for VDS solution
    // This property is expected to be setup once during bootup
    if( (property_get("persist.hwc.enable_vds", value, NULL) > 0) &&
        ((!strncmp(value, "1", strlen("1"))) ||
        !strncasecmp(value, "true", strlen("true")))) {
        //HAL virtual display is using VDS based implementation
        mVDSEnabled = true;
    }

    if (needVSyncThread) {
        // we don't have VSYNC support, we need to fake it
        mVSyncThread = new VSyncThread(*this);
+4 −1
Original line number Diff line number Diff line
@@ -121,6 +121,9 @@ public:
    // the release fence is only valid after commit()
    sp<Fence> getAndResetReleaseFence(int32_t id);

    // is VDS solution enabled
    inline bool isVDSEnabled() const { return mVDSEnabled; };

    // needed forward declarations
    class LayerListIterator;

@@ -362,7 +365,7 @@ private:
    sp<VSyncThread>                 mVSyncThread;
    bool                            mDebugForceFakeVSync;
    BitSet32                        mAllocatedDisplayIDs;

    bool                            mVDSEnabled;
    // protected by mLock
    mutable Mutex mLock;
    // synchronization between Draw call and Dumpsys call
+75 −27
Original line number Diff line number Diff line
@@ -1235,6 +1235,78 @@ void SurfaceFlinger::setVirtualDisplayData(
    mHwc->setVirtualDisplayProperties(hwcDisplayId, w, h, format);
}

void SurfaceFlinger::configureVirtualDisplay(int32_t &hwcDisplayId,
                                        sp<DisplaySurface> &dispSurface,
                                        sp<IGraphicBufferProducer> &producer,
                                        const DisplayDeviceState state,
                                        sp<IGraphicBufferProducer> bqProducer,
                                        sp<IGraphicBufferConsumer> bqConsumer)
{
    bool vdsEnabled = mHwc->isVDSEnabled();

    //for V4L2 based virtual display implementation
    if(!vdsEnabled) {
        // persist.sys.wfd.virtual will be set if WFD is launched via
        // settings app. This is currently being done in
        // ExtendedRemoteDisplay-WFD stack.
        // This flag will be reset at the time of disconnection of virtual WFD
        // display.
        // This flag is set to zero if WFD is launched via QCOM WFD
        // proprietary APIs which use HDMI piggyback approach.
        char value[PROPERTY_VALUE_MAX];
        property_get("persist.sys.wfd.virtual", value, "0");
        int wfdVirtual = atoi(value);
        if(!wfdVirtual) {
            // This is for non-wfd virtual display scenarios(e.g. SSD/SR/CTS)
            sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
                    hwcDisplayId, state.surface, bqProducer, bqConsumer, state.displayName);
            dispSurface = vds;
            // There won't be any interaction with HWC for this virtual display.
            // so the GLES driver can pass buffers directly to the sink.
            producer = state.surface;
        } else {
            hwcDisplayId = allocateHwcDisplayId(state.type);
            if (hwcDisplayId >= 0) {
                // This is for WFD virtual display scenario.
                // Read virtual display properties and create a
                // rendering surface for it inorder to be handled by hwc.
                setVirtualDisplayData(hwcDisplayId, state.surface);
                dispSurface = new FramebufferSurface(*mHwc, state.type,
                bqConsumer);
                producer = bqProducer;
            } else {
                // in case of WFD Virtual + SSD/SR concurrency scenario,
                // WFD virtual display instance gets valid hwcDisplayId and
                // SSD/SR will get invalid hwcDisplayId
                sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
                        hwcDisplayId, state.surface, bqProducer, bqConsumer, state.displayName);
                dispSurface = vds;
                // There won't be any interaction with HWC for this virtual
                // display, so the GLES driver can pass buffers directly to the
                // sink.
                producer = state.surface;
            }
        }
    } else {
        // VDS solution is enabled
        // HWC is allocated for first virtual display.
        // Subsequent virtual display sessions will be composed by GLES driver.
        // ToDo: Modify VDS component to allocate hwcDisplayId based on
        // mForceHwcCopy (which is based on Usage Flags)

        sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(*mHwc,
                hwcDisplayId, state.surface, bqProducer, bqConsumer, state.displayName);
        dispSurface = vds;
        if (hwcDisplayId >= 0) {
            producer = vds;
        } else {
            // There won't be any interaction with HWC for this virtual display,
            // so the GLES driver can pass buffers directly to the sink.
            producer = state.surface;
        }
    }
}

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
@@ -1384,33 +1456,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
                        // they have external state (layer stack, projection,
                        // etc.) but no internal state (i.e. a DisplayDevice).
                        if (state.surface != NULL) {

                            char value[PROPERTY_VALUE_MAX];
                            hwcDisplayId = allocateHwcDisplayId(state.type);
                            property_get("persist.sys.wfd.virtual", value, "0");
                            int wfdVirtual = atoi(value);
                            if(!wfdVirtual) {
                                sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
                                        *mHwc, hwcDisplayId, state.surface,
                                        bqProducer, bqConsumer, state.displayName);
                                if (hwcDisplayId >= 0) {
                                   producer = vds;
                                } else {
                                  // There won't be any interaction with HWC for this virtual display,
                                  // so the GLES driver can pass buffers directly to the sink.
                                  producer = state.surface;
                                }
                            } else {
                                //Read virtual display properties and create a
                                //rendering surface for it inorder to be handled
                                //by hwc.
                                setVirtualDisplayData(hwcDisplayId,
                                                                 state.surface);
                                dispSurface = new FramebufferSurface(*mHwc,
                                                                    state.type,
                            configureVirtualDisplay(hwcDisplayId,
                                    dispSurface, producer, state, bqProducer,
                                    bqConsumer);
                                producer = bqProducer;
                            }
                        }
                    } else {
                        ALOGE_IF(state.surface!=NULL,
+10 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@

#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/BufferQueue.h>

#include <hardware/hwcomposer_defs.h>

@@ -260,6 +261,15 @@ private:
    void setVirtualDisplayData( int32_t hwcDisplayId,
                                const sp<IGraphicBufferProducer>& sink);

    // Configure Virtual Display parameters such as the display surface
    // and the buffer queue
    void configureVirtualDisplay(int32_t &hwcDisplayId,
            sp<DisplaySurface> &dispSurface,
            sp<IGraphicBufferProducer> &producer,
            const DisplayDeviceState state,
            sp<IGraphicBufferProducer> bqProducer,
            sp<IGraphicBufferConsumer> bqConsumer);

    /* handlePageFilp: this is were we latch a new buffer
     * if available and compute the dirty region.
     */