Hwcomposer: Enable VirtualDisplay feature
JIRA: MARVIN-68
Fixed fd leaks issues with VirtualDisplays.
Due to removal of WIDI, the VirtualDisplay feature got removed
and we end up with a file descriptor leakage when using
extensively the VirtualDisplay feature.
Add back VirtualDisplay feature without WIDI support.
Change-Id: Ief60aac960585c0f09312e2cc7e5629969f3f448
Signed-off-by: Liang Weilong <weilongx.liang@intel.com>
Signed-off-by: Guillaume Ranquet <guillaumex.ranquet@intel.com>
Reviewed-on: https://android.intel.com/380907
Reviewed-by: Tasayco Loarte, VictorX <victorx.tasayco.loarte@intel.com>
Reviewed-by: Liu, Kevin <kevin.liu@intel.com>
Reviewed-by: jenkins_ndg <jenkins_ndg@intel.com>
Reviewed-by: Akue, LoicX <loicx.akue@intel.com>
Reviewed-by: Ledentec, AlexandreX <alexandrex.ledentec@intel.com>
Reviewed-by: Maalem, Saadi <saadi.maalem@intel.com>
Tested-by: Tasayco Loarte, VictorX <victorx.tasayco.loarte@intel.com>
diff --git a/merrifield/common/base/DisplayAnalyzer.cpp b/merrifield/common/base/DisplayAnalyzer.cpp
index 5da7403..a0b9ffd 100755
--- a/merrifield/common/base/DisplayAnalyzer.cpp
+++ b/merrifield/common/base/DisplayAnalyzer.cpp
@@ -24,9 +24,7 @@
#include <cutils/properties.h>
#include <GraphicBuffer.h>
#include <ExternalDevice.h>
-#ifdef INTEL_WIDI_MERRIFIELD
#include <VirtualDevice.h>
-#endif
namespace android {
namespace intel {
@@ -136,19 +134,12 @@
Hwcomposer *hwc = &Hwcomposer::getInstance();
ExternalDevice *eDev = static_cast<ExternalDevice *>(hwc->getDisplayDevice(IDisplayDevice::DEVICE_EXTERNAL));
-#ifdef INTEL_WIDI_MERRIFIELD
VirtualDevice *vDev = static_cast<VirtualDevice *>(hwc->getDisplayDevice(IDisplayDevice::DEVICE_VIRTUAL));
if ((!eDev || !eDev->isConnected()) && (!vDev || !vDev->isFrameServerActive())) {
mVideoExtModeEligible = false;
return;
}
-#else
- if (!eDev || !eDev->isConnected()) {
- mVideoExtModeEligible = false;
- return;
- }
-#endif /*INTEL_WIDI_MERRIFIELD*/
bool geometryChanged = false;
int activeDisplays = 0;
diff --git a/merrifield/common/base/VsyncManager.cpp b/merrifield/common/base/VsyncManager.cpp
index 56e935e..37fa0e7 100644
--- a/merrifield/common/base/VsyncManager.cpp
+++ b/merrifield/common/base/VsyncManager.cpp
@@ -156,7 +156,6 @@
return IDisplayDevice::DEVICE_EXTERNAL;
}
-#ifdef INTEL_WIDI_MERRIFIELD
// use vsync from virtual display when video extended mode is entered
if (Hwcomposer::getInstance().getDisplayAnalyzer()->isVideoExtModeActive()) {
device = getDisplayDevice(IDisplayDevice::DEVICE_VIRTUAL);
@@ -165,7 +164,6 @@
}
WTRACE("Could not use vsync from secondary device");
}
-#endif
return IDisplayDevice::DEVICE_PRIMARY;
}
diff --git a/merrifield/common/devices/VirtualDevice.cpp b/merrifield/common/devices/VirtualDevice.cpp
index a4396d7..965c633 100755
--- a/merrifield/common/devices/VirtualDevice.cpp
+++ b/merrifield/common/devices/VirtualDevice.cpp
@@ -480,26 +480,34 @@
struct VirtualDevice::FrameTypeChangedTask : public VirtualDevice::Task {
virtual void run(VirtualDevice& vd) {
+#ifdef INTEL_WIDI
typeChangeListener->frameTypeChanged(inputFrameInfo);
ITRACE("Notify frameTypeChanged: %dx%d in %dx%d @ %d fps",
inputFrameInfo.contentWidth, inputFrameInfo.contentHeight,
inputFrameInfo.bufferWidth, inputFrameInfo.bufferHeight,
inputFrameInfo.contentFrameRateN);
+#endif
}
+#ifdef INTEL_WIDI
sp<IFrameTypeChangeListener> typeChangeListener;
FrameInfo inputFrameInfo;
+#endif
};
struct VirtualDevice::BufferInfoChangedTask : public VirtualDevice::Task {
virtual void run(VirtualDevice& vd) {
+#ifdef INTEL_WIDI
typeChangeListener->bufferInfoChanged(outputFrameInfo);
ITRACE("Notify bufferInfoChanged: %dx%d in %dx%d @ %d fps",
outputFrameInfo.contentWidth, outputFrameInfo.contentHeight,
outputFrameInfo.bufferWidth, outputFrameInfo.bufferHeight,
outputFrameInfo.contentFrameRateN);
+#endif
}
+#ifdef INTEL_WIDI
sp<IFrameTypeChangeListener> typeChangeListener;
FrameInfo outputFrameInfo;
+#endif
};
struct VirtualDevice::OnFrameReadyTask : public VirtualDevice::Task {
@@ -513,7 +521,7 @@
//from the vector properly even if the notifyBufferReturned call acquires mHeldBuffersLock first.
vd.mHeldBuffers.add(handle, heldBuffer);
}
-
+#ifdef INTEL_WIDI
// FIXME: we could remove this casting once onFrameReady receives
// a buffer_handle_t handle
status_t result = frameListener->onFrameReady((uint32_t)handle, handleType, renderTimestamp, mediaTimestamp);
@@ -521,12 +529,18 @@
Mutex::Autolock _l(vd.mHeldBuffersLock);
vd.mHeldBuffers.removeItem(handle);
}
+#else
+ Mutex::Autolock _l(vd.mHeldBuffersLock);
+ vd.mHeldBuffers.removeItem(handle);
+#endif
}
sp<RenderTask> renderTask;
sp<RefBase> heldBuffer;
- sp<IFrameListener> frameListener;
buffer_handle_t handle;
+#ifdef INTEL_WIDI
+ sp<IFrameListener> frameListener;
HWCBufferHandleType handleType;
+#endif
int64_t renderTimestamp;
int64_t mediaTimestamp;
};
@@ -642,7 +656,9 @@
mDecHeight(0)
{
CTRACE();
+#ifdef INTEL_WIDI
mNextConfig.frameServerActive = false;
+#endif
}
VirtualDevice::~VirtualDevice()
@@ -686,7 +702,7 @@
return true;
}
-
+#ifdef INTEL_WIDI
status_t VirtualDevice::start(sp<IFrameTypeChangeListener> typeChangeListener)
{
ITRACE();
@@ -730,12 +746,17 @@
}
return NO_ERROR;
}
+#endif
bool VirtualDevice::isFrameServerActive() const
{
+#ifdef INTEL_WIDI
return mCurrentConfig.frameServerActive;
+#endif
+ return false;
}
+#ifdef INTEL_WIDI
/* TODO: 64-bit - this handle of size 32-bit is a problem for 64-bit */
status_t VirtualDevice::notifyBufferReturned(int handle)
{
@@ -759,7 +780,7 @@
mNextConfig.policy = policy;
return NO_ERROR;
}
-
+#endif
static bool canUseDirectly(const hwc_display_contents_1_t *display, size_t n)
{
const hwc_layer_1_t& fbTarget = display->hwLayers[display->numHwLayers-1];
@@ -792,11 +813,12 @@
mVspInUse = false;
mExpectAcquireFences = false;
mIsForceCloneMode = false;
-
+#ifdef INTEL_WIDI
{
Mutex::Autolock _l(mConfigLock);
mCurrentConfig = mNextConfig;
}
+#endif
bool shouldBeConnected = (display != NULL);
if (shouldBeConnected != mLastConnectionStatus) {
@@ -822,12 +844,17 @@
return true;
}
+#ifdef INTEL_WIDI
if (!mCurrentConfig.frameServerActive) {
// We're done with CSC buffers, since we blit to outbuf in this mode.
// We want to keep mappings cached, so we don't clear mMappedBufferCache.
Mutex::Autolock _l(mTaskLock);
mCscBuffers.clear();
}
+#else
+ Mutex::Autolock _l(mTaskLock);
+ mCscBuffers.clear();
+#endif
// by default send the FRAMEBUFFER_TARGET layer (composited image)
const ssize_t fbTarget = display->numHwLayers-1;
@@ -837,7 +864,7 @@
DisplayAnalyzer *analyzer = mHwc.getDisplayAnalyzer();
mProtectedMode = false;
-
+#ifdef INTEL_WIDI
if (mCurrentConfig.typeChangeListener != NULL &&
!analyzer->isOverlayAllowed() &&
analyzer->getVideoInstances() <= 1) {
@@ -879,13 +906,14 @@
break;
}
}
+#endif
if (mYuvLayer == -1) {
mFirstVideoFrame = true;
mDecWidth = 0;
mDecHeight = 0;
}
-
+#ifdef INTEL_WIDI
if (mCurrentConfig.frameServerActive && mCurrentConfig.extendedModeEnabled && mYuvLayer != -1) {
if (handleExtendedMode(display)) {
mYuvLayer = -1;
@@ -903,7 +931,7 @@
mIsForceCloneMode = true;
mYuvLayer = -1;
}
-
+#endif
if (mYuvLayer == 0 && fbTarget == 1) {
// No RGB layer, so tell queueCompose to use blank RGB in fbtarget.
mRgbLayer = -1;
@@ -933,10 +961,11 @@
// This has no effect when the video is the bottommost layer.
display->hwLayers[mYuvLayer].hints |= HWC_HINT_CLEAR_FB;
+#ifdef INTEL_WIDI
// we're streaming fbtarget, so send onFramePrepare and wait for composition to happen
if (mCurrentConfig.frameListener != NULL)
mCurrentConfig.frameListener->onFramePrepare(mRenderTimestamp, -1);
-
+#endif
return true;
}
@@ -1003,7 +1032,11 @@
ETRACE("No video handle");
return false;
}
+#ifdef INTEL_WIDI
if (!mCurrentConfig.frameServerActive && display->outbuf == NULL) {
+#else
+ if (display->outbuf == NULL) {
+#endif
ETRACE("No outbuf");
return true; // fallback would be pointless
}
@@ -1021,6 +1054,7 @@
composeTask->outHeight = fbTarget.sourceCropf.bottom - fbTarget.sourceCropf.top;
bool scaleRgb = false;
+#ifdef INTEL_WIDI
if (mCurrentConfig.frameServerActive) {
if (mVspUpscale) {
composeTask->outWidth = mCurrentConfig.policy.scaledWidth;
@@ -1039,6 +1073,9 @@
} else {
composeTask->outputHandle = display->outbuf;
}
+#else
+ composeTask->outputHandle = display->outbuf;
+#endif
vspPrepare(composeTask->outWidth, composeTask->outHeight);
@@ -1258,7 +1295,7 @@
mTasks.push_back(composeTask);
mRequestQueued.signal();
-
+#ifdef INTEL_WIDI
if (mCurrentConfig.frameServerActive) {
FrameInfo inputFrameInfo;
@@ -1315,6 +1352,9 @@
else {
display->retireFenceFd = dup(retireFd);
}
+#else
+ display->retireFenceFd = dup(retireFd);
+#endif
return true;
}
@@ -1376,7 +1416,7 @@
// Framebuffer after BlitTask::run() calls sw_sync_timeline_inc().
layer.releaseFenceFd = sw_sync_fence_create(mSyncTimelineFd, "widi_blit_retire", mNextSyncPoint);
mNextSyncPoint++;
-
+#ifdef INTEL_WIDI
if (mCurrentConfig.frameServerActive) {
blitTask->destHandle = mCscBuffers.get(blitTask->destRect.w, blitTask->destRect.h, &heldBuffer);
blitTask->destAcquireFenceFd = -1;
@@ -1394,7 +1434,13 @@
display->outbufAcquireFenceFd = -1;
display->retireFenceFd = dup(layer.releaseFenceFd);
}
-
+#else
+ blitTask->destHandle = display->outbuf;
+ blitTask->destAcquireFenceFd = display->outbufAcquireFenceFd;
+ // don't let TngDisplayContext::commitEnd() close this
+ display->outbufAcquireFenceFd = -1;
+ display->retireFenceFd = dup(layer.releaseFenceFd);
+#endif
if (blitTask->destHandle == NULL) {
WTRACE("Out of CSC buffers, dropping frame");
return false;
@@ -1402,7 +1448,7 @@
mTasks.push_back(blitTask);
mRequestQueued.signal();
-
+#ifdef INTEL_WIDI
if (mCurrentConfig.frameServerActive) {
FrameInfo inputFrameInfo;
memset(&inputFrameInfo, 0, sizeof(inputFrameInfo));
@@ -1444,10 +1490,10 @@
mTasks.push_back(frameReadyTask);
}
}
-
+#endif
return true;
}
-
+#ifdef INTEL_WIDI
bool VirtualDevice::handleExtendedMode(hwc_display_contents_1_t *display)
{
FrameInfo inputFrameInfo;
@@ -1689,6 +1735,7 @@
mTasks.push_back(notifyTask);
}
}
+#endif
void VirtualDevice::colorSwap(buffer_handle_t src, buffer_handle_t dest, uint32_t pixelCount)
{
@@ -2169,6 +2216,9 @@
bool VirtualDevice::initialize()
{
+ mRgbLayer = -1;
+ mYuvLayer = -1;
+#ifdef INTEL_WIDI
// Add initialization codes here. If init fails, invoke DEINIT_AND_RETURN_FALSE();
mNextConfig.typeChangeListener = NULL;
mNextConfig.policy.scaledWidth = 0;
@@ -2180,12 +2230,10 @@
mNextConfig.forceNotifyFrameType = false;
mNextConfig.forceNotifyBufferInfo = false;
mCurrentConfig = mNextConfig;
- mRgbLayer = -1;
- mYuvLayer = -1;
memset(&mLastInputFrameInfo, 0, sizeof(mLastInputFrameInfo));
memset(&mLastOutputFrameInfo, 0, sizeof(mLastOutputFrameInfo));
-
+#endif
mPayloadManager = mHwc.getPlatFactory()->createVideoPayloadManager();
if (!mPayloadManager) {
@@ -2204,6 +2252,7 @@
mThread = new WidiBlitThread(this);
mThread->run("WidiBlit", PRIORITY_URGENT_DISPLAY);
+#ifdef INTEL_WIDI
// Publish frame server service with service manager
status_t ret = defaultServiceManager()->addService(String16("hwc.widi"), this);
if (ret == NO_ERROR) {
@@ -2213,7 +2262,9 @@
ETRACE("Could not register hwc.widi with service manager, error = %d", ret);
deinitialize();
}
-
+#else
+ mInitialized = true;
+#endif
mVspEnabled = false;
mVspInUse = false;
mVspWidth = 0;
diff --git a/merrifield/include/IDisplayDevice.h b/merrifield/include/IDisplayDevice.h
index d9a6ac2..ad99a2f 100644
--- a/merrifield/include/IDisplayDevice.h
+++ b/merrifield/include/IDisplayDevice.h
@@ -55,9 +55,7 @@
enum {
DEVICE_PRIMARY = HWC_DISPLAY_PRIMARY,
DEVICE_EXTERNAL = HWC_DISPLAY_EXTERNAL,
-#ifdef INTEL_WIDI_MERRIFIELD
DEVICE_VIRTUAL = HWC_DISPLAY_VIRTUAL,
-#endif
DEVICE_COUNT,
};
enum {
diff --git a/merrifield/include/VirtualDevice.h b/merrifield/include/VirtualDevice.h
index 2af3c6b..a2ae7d4 100755
--- a/merrifield/include/VirtualDevice.h
+++ b/merrifield/include/VirtualDevice.h
@@ -22,9 +22,10 @@
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/Vector.h>
-
+#include <utils/List.h>
+#ifdef INTEL_WIDI
#include "IFrameServer.h"
-
+#endif
#include <va/va.h>
#include <va/va_vpp.h>
@@ -36,7 +37,11 @@
class IVideoPayloadManager;
class SoftVsyncObserver;
+#ifdef INTEL_WIDI
class VirtualDevice : public IDisplayDevice, public BnFrameServer {
+#else
+class VirtualDevice : public IDisplayDevice, public RefBase{
+#endif
protected:
class VAMappedHandle;
class VAMappedHandleObject;
@@ -54,6 +59,7 @@
android::sp<VirtualDevice> vd;
android::sp<CachedBuffer> cachedBuffer;
};
+#ifdef INTEL_WIDI
struct Configuration {
sp<IFrameTypeChangeListener> typeChangeListener;
sp<IFrameListener> frameListener;
@@ -63,6 +69,7 @@
bool forceNotifyFrameType;
bool forceNotifyBufferInfo;
};
+#endif
class BufferList {
public:
BufferList(VirtualDevice& vd, const char* name, uint32_t limit, uint32_t format, uint32_t usage);
@@ -91,8 +98,10 @@
struct OnFrameReadyTask;
Mutex mConfigLock;
+#ifdef INTEL_WIDI
Configuration mCurrentConfig;
Configuration mNextConfig;
+#endif
ssize_t mRgbLayer;
ssize_t mYuvLayer;
bool mProtectedMode;
@@ -114,10 +123,10 @@
int mSyncTimelineFd;
unsigned mNextSyncPoint;
bool mExpectAcquireFences;
-
+#ifdef INTEL_WIDI
FrameInfo mLastInputFrameInfo;
FrameInfo mLastOutputFrameInfo;
-
+#endif
int32_t mVideoFramerate;
android::KeyedVector<buffer_handle_t, android::sp<CachedBuffer> > mMappedBufferCache;
@@ -147,11 +156,12 @@
bool sendToWidi(hwc_display_contents_1_t *display);
bool queueCompose(hwc_display_contents_1_t *display);
bool queueColorConvert(hwc_display_contents_1_t *display);
+#ifdef INTEL_WIDI
bool handleExtendedMode(hwc_display_contents_1_t *display);
void queueFrameTypeInfo(const FrameInfo& inputFrameInfo);
void queueBufferInfo(const FrameInfo& outputFrameInfo);
-
+#endif
void colorSwap(buffer_handle_t src, buffer_handle_t dest, uint32_t pixelCount);
void vspPrepare(uint32_t width, uint32_t height);
void vspEnable(uint32_t width, uint32_t height);
@@ -189,13 +199,14 @@
virtual int getType() const;
virtual void onVsync(int64_t timestamp);
virtual void dump(Dump& d);
-
+#ifdef INTEL_WIDI
// IFrameServer methods
virtual android::status_t start(sp<IFrameTypeChangeListener> frameTypeChangeListener);
virtual android::status_t stop(bool isConnected);
/* TODO: 64-bit - this handle of size 32-bit is a problem for 64-bit */
virtual android::status_t notifyBufferReturned(int handle);
virtual android::status_t setResolution(const FrameProcessingPolicy& policy, android::sp<IFrameListener> listener);
+#endif
virtual bool setPowerMode(int mode);
virtual int getActiveConfig();
virtual bool setActiveConfig(int index);
diff --git a/merrifield/ips/tangier/TngDisplayContext.cpp b/merrifield/ips/tangier/TngDisplayContext.cpp
index 7f94185..90218d4 100644
--- a/merrifield/ips/tangier/TngDisplayContext.cpp
+++ b/merrifield/ips/tangier/TngDisplayContext.cpp
@@ -219,19 +219,15 @@
displays[i]->hwLayers[j].releaseFenceFd);
}
-#ifdef INTEL_WIDI_MERRIFIELD
// retireFence is used for SurfaceFlinger to do DispSync;
// dup releaseFenceFd for physical displays and ignore virtual
// display; we don't distinguish between release and retire, and all
// physical displays are using a single releaseFence; for virtual
// display, fencing is handled by the VirtualDisplay class
if (i < IDisplayDevice::DEVICE_VIRTUAL) {
-#endif
displays[i]->retireFenceFd =
(releaseFenceFd != -1) ? dup(releaseFenceFd) : -1;
-#ifdef INTEL_WIDI_MERRIFIELD
}
-#endif
}
// close original release fence fd
diff --git a/merrifield/platforms/merrifield/Android.mk b/merrifield/platforms/merrifield/Android.mk
index 98e1d3d..6db9243 100644
--- a/merrifield/platforms/merrifield/Android.mk
+++ b/merrifield/platforms/merrifield/Android.mk
@@ -37,6 +37,7 @@
../../common/devices/PhysicalDevice.cpp \
../../common/devices/PrimaryDevice.cpp \
../../common/devices/ExternalDevice.cpp \
+ ../../common/devices/VirtualDevice.cpp \
../../common/observers/UeventObserver.cpp \
../../common/observers/VsyncEventObserver.cpp \
../../common/observers/SoftVsyncObserver.cpp \
@@ -115,12 +116,9 @@
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
LOCAL_CFLAGS += -DLINUX
-ifeq ($(INTEL_WIDI_MERRIFIELD), true)
-LOCAL_SRC_FILES += \
- ../../common/devices/VirtualDevice.cpp
-
+ifeq ($(INTEL_WIDI), true)
LOCAL_SHARED_LIBRARIES += libhwcwidi libbinder
- LOCAL_CFLAGS += -DINTEL_WIDI_MERRIFIELD
+ LOCAL_CFLAGS += -DINTEL_WIDI
endif
ifeq ($(TARGET_HAS_MULTIPLE_DISPLAY),true)
diff --git a/merrifield/platforms/merrifield/PlatFactory.cpp b/merrifield/platforms/merrifield/PlatFactory.cpp
index 7530225..45b7ade 100644
--- a/merrifield/platforms/merrifield/PlatFactory.cpp
+++ b/merrifield/platforms/merrifield/PlatFactory.cpp
@@ -21,9 +21,7 @@
#include <IDisplayDevice.h>
#include <PrimaryDevice.h>
#include <ExternalDevice.h>
-#ifdef INTEL_WIDI_MERRIFIELD
#include <VirtualDevice.h>
-#endif
#include <Hwcomposer.h>
#include <PlatFactory.h>
#include <common/VsyncControl.h>
@@ -76,10 +74,8 @@
return new PrimaryDevice(hwc, new PlatDeviceControlFactory());
case IDisplayDevice::DEVICE_EXTERNAL:
return new ExternalDevice(hwc, new PlatDeviceControlFactory());
-#ifdef INTEL_WIDI_MERRIFIELD
case IDisplayDevice::DEVICE_VIRTUAL:
return new VirtualDevice(hwc);
-#endif
default:
ETRACE("invalid display device %d", disp);
return NULL;
diff --git a/merrifield/platforms/merrifield_plus/Android.mk b/merrifield/platforms/merrifield_plus/Android.mk
index 2f5f63d..0a85355 100644
--- a/merrifield/platforms/merrifield_plus/Android.mk
+++ b/merrifield/platforms/merrifield_plus/Android.mk
@@ -37,6 +37,7 @@
../../common/devices/PhysicalDevice.cpp \
../../common/devices/PrimaryDevice.cpp \
../../common/devices/ExternalDevice.cpp \
+ ../../common/devices/VirtualDevice.cpp \
../../common/observers/UeventObserver.cpp \
../../common/observers/VsyncEventObserver.cpp \
../../common/observers/SoftVsyncObserver.cpp \
@@ -118,13 +119,9 @@
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
LOCAL_CFLAGS += -DLINUX
-#$(error local path is: $(LOCAL_C_INCLUDES))
-ifeq ($(INTEL_WIDI_MERRIFIELD), true)
-LOCAL_SRC_FILES += \
- ../../common/devices/VirtualDevice.cpp
-
+ifeq ($(INTEL_WIDI), true)
LOCAL_SHARED_LIBRARIES += libhwcwidi libbinder
- LOCAL_CFLAGS += -DINTEL_WIDI_MERRIFIELD
+ LOCAL_CFLAGS += -DINTEL_WIDI
endif
ifeq ($(TARGET_HAS_MULTIPLE_DISPLAY),true)
diff --git a/merrifield/platforms/merrifield_plus/PlatFactory.cpp b/merrifield/platforms/merrifield_plus/PlatFactory.cpp
index 095a4a1..d35635b 100644
--- a/merrifield/platforms/merrifield_plus/PlatFactory.cpp
+++ b/merrifield/platforms/merrifield_plus/PlatFactory.cpp
@@ -74,10 +74,8 @@
return new PrimaryDevice(hwc, new PlatDeviceControlFactory());
case IDisplayDevice::DEVICE_EXTERNAL:
return new ExternalDevice(hwc, new PlatDeviceControlFactory());
-#ifdef INTEL_WIDI_MERRIFIELD
case IDisplayDevice::DEVICE_VIRTUAL:
return new VirtualDevice(hwc);
-#endif
default:
ETRACE("invalid display device %d", disp);
return NULL;