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
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e0558ab..bd64601 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1235,6 +1235,78 @@
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 @@
// 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,
- bqConsumer);
- producer = bqProducer;
- }
+ configureVirtualDisplay(hwcDisplayId,
+ dispSurface, producer, state, bqProducer,
+ bqConsumer);
}
} else {
ALOGE_IF(state.surface!=NULL,