Bug 1138287 - Part 2: Support multi-screen on Gonk platform. r=mwu, r=sotaro, r=jgilbert, r=mattwoodrow
authorShelly Lin <slin@mozilla.com>
Fri, 05 Jun 2015 11:29:30 +0800
changeset 247752 fed42e7cad9494a2b16eb69cd7617eafd2d152c3
parent 247751 3def91c9ff2408e3c42278386b860a5968eacebd
child 247753 8870e950afc5230fa3ea289fb762d0d751d8e83e
push id28882
push userkwierso@gmail.com
push dateWed, 10 Jun 2015 02:25:43 +0000
treeherdermozilla-central@5787d784485e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu, sotaro, jgilbert, mattwoodrow
bugs1138287
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1138287 - Part 2: Support multi-screen on Gonk platform. r=mwu, r=sotaro, r=jgilbert, r=mattwoodrow
gfx/gl/GLContextProviderEGL.cpp
gfx/layers/composite/LayerManagerComposite.cpp
gfx/layers/opengl/Composer2D.h
gfx/layers/opengl/CompositorOGL.cpp
widget/gonk/HwcComposer2D.cpp
widget/gonk/HwcComposer2D.h
widget/gonk/libdisplay/GonkDisplay.h
widget/gonk/libdisplay/GonkDisplayICS.cpp
widget/gonk/libdisplay/GonkDisplayICS.h
widget/gonk/libdisplay/GonkDisplayJB.cpp
widget/gonk/libdisplay/GonkDisplayJB.h
widget/gonk/nsScreenManagerGonk.cpp
widget/gonk/nsScreenManagerGonk.h
widget/gonk/nsWindow.cpp
widget/gonk/nsWindow.h
widget/moz.build
widget/nsIDisplayInfo.idl
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -14,16 +14,18 @@
 // we're using default display for now
 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
 #elif defined(MOZ_WIDGET_QT)
 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)(aWidget->GetNativeData(NS_NATIVE_SHAREABLE_WINDOW))
 #elif defined(MOZ_WIDGET_GONK)
 #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
 #include "HwcComposer2D.h"
 #include "libdisplay/GonkDisplay.h"
+#include "nsWindow.h"
+#include "nsScreenManagerGonk.h"
 #endif
 
 #if defined(ANDROID)
 /* from widget */
 #if defined(MOZ_WIDGET_ANDROID)
 #include "AndroidBridge.h"
 #endif
 
@@ -123,17 +125,17 @@ namespace gl {
     (_array).AppendElement(_v);                 \
 } while (0)
 
 #define ADD_ATTR_1(_array, _k) do {             \
     (_array).AppendElement(_k);                 \
 } while (0)
 
 static bool
-CreateConfig(EGLConfig* aConfig);
+CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget);
 
 // append three zeros at the end of attribs list to work around
 // EGL implementation bugs that iterate until they find 0, instead of
 // EGL_NONE. See bug 948406.
 #define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \
      LOCAL_EGL_NONE, 0, 0, 0
 
 static EGLint gTerminationAttribs[] = {
@@ -478,17 +480,17 @@ GLContextEGL::HoldSurface(gfxASurface *a
 GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
 {
     if (!sEGLLibrary.EnsureInitialized()) {
         MOZ_CRASH("Failed to load EGL library!\n");
         return nullptr;
     }
 
     EGLConfig config;
-    if (!CreateConfig(&config)) {
+    if (!CreateConfig(&config, aWidget)) {
         MOZ_CRASH("Failed to create EGLConfig!\n");
         return nullptr;
     }
 
     EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
     return surface;
 }
 
@@ -632,17 +634,17 @@ static const EGLint kEGLConfigAttribsRGB
     LOCAL_EGL_ALPHA_SIZE,      8,
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
     LOCAL_EGL_FRAMEBUFFER_TARGET_ANDROID, LOCAL_EGL_TRUE,
 #endif
     EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
 };
 
 static bool
-CreateConfig(EGLConfig* aConfig, int32_t depth)
+CreateConfig(EGLConfig* aConfig, int32_t depth, nsIWidget* aWidget)
 {
     EGLConfig configs[64];
     const EGLint* attribs;
     EGLint ncfg = ArrayLength(configs);
 
     switch (depth) {
         case 16:
             attribs = kEGLConfigAttribsRGB16;
@@ -668,22 +670,23 @@ CreateConfig(EGLConfig* aConfig, int32_t
     // On gonk, it's important to select a configuration with the
     // the correct order as well as bits per channel.
     // EGL_NATIVE_VISUAL_ID gives us the Android pixel format which
     // is an enum that tells us both order and bits per channel.
     // For example -
     //  HAL_PIXEL_FORMAT_RGBX_8888
     //  HAL_PIXEL_FORMAT_BGRA_8888
     //  HAL_PIXEL_FORMAT_RGB_565
+    nsWindow* window = static_cast<nsWindow*>(aWidget);
     for (int j = 0; j < ncfg; ++j) {
         EGLConfig config = configs[j];
         EGLint format;
         if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
                                          LOCAL_EGL_NATIVE_VISUAL_ID, &format) &&
-            format == GetGonkDisplay()->surfaceformat)
+            format == window->GetScreen()->GetSurfaceFormat())
         {
             *aConfig = config;
             return true;
         }
     }
 #endif
 
     for (int j = 0; j < ncfg; ++j) {
@@ -709,30 +712,30 @@ CreateConfig(EGLConfig* aConfig, int32_t
 }
 
 // Return true if a suitable EGLConfig was found and pass it out
 // through aConfig.  Return false otherwise.
 //
 // NB: It's entirely legal for the returned EGLConfig to be valid yet
 // have the value null.
 static bool
-CreateConfig(EGLConfig* aConfig)
+CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget)
 {
     int32_t depth = gfxPlatform::GetPlatform()->GetScreenDepth();
-    if (!CreateConfig(aConfig, depth)) {
+    if (!CreateConfig(aConfig, depth, aWidget)) {
 #ifdef MOZ_WIDGET_ANDROID
         // Bug 736005
         // Android doesn't always support 16 bit so also try 24 bit
         if (depth == 16) {
-            return CreateConfig(aConfig, 24);
+            return CreateConfig(aConfig, 24, aWidget);
         }
         // Bug 970096
         // Some devices that have 24 bit screens only support 16 bit OpenGL?
         if (depth == 24) {
-            return CreateConfig(aConfig, 16);
+            return CreateConfig(aConfig, 16, aWidget);
         }
 #endif
         return false;
     } else {
         return true;
     }
 }
 
@@ -767,17 +770,17 @@ GLContextProviderEGL::CreateForWindow(ns
     if (!sEGLLibrary.EnsureInitialized()) {
         MOZ_CRASH("Failed to load EGL library!\n");
         return nullptr;
     }
 
     bool doubleBuffered = true;
 
     EGLConfig config;
-    if (!CreateConfig(&config)) {
+    if (!CreateConfig(&config, aWidget)) {
         MOZ_CRASH("Failed to create EGLConfig!\n");
         return nullptr;
     }
 
     EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config);
 
     if (surface == EGL_NO_SURFACE) {
         MOZ_CRASH("Failed to create EGLSurface!\n");
@@ -806,17 +809,17 @@ GLContextProviderEGL::CreateForWindow(ns
 EGLSurface
 GLContextProviderEGL::CreateEGLSurface(void* aWindow)
 {
     if (!sEGLLibrary.EnsureInitialized()) {
         MOZ_CRASH("Failed to load EGL library!\n");
     }
 
     EGLConfig config;
-    if (!CreateConfig(&config)) {
+    if (!CreateConfig(&config, static_cast<nsIWidget*>(aWindow))) {
         MOZ_CRASH("Failed to create EGLConfig!\n");
     }
 
     MOZ_ASSERT(aWindow);
 
     EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow, 0);
 
     if (surface == EGL_NO_SURFACE) {
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -661,17 +661,18 @@ LayerManagerComposite::Render()
 
   /** Our more efficient but less powerful alter ego, if one is available. */
   nsRefPtr<Composer2D> composer2D;
   composer2D = mCompositor->GetWidget()->GetComposer2D();
 
   // We can't use composert2D if we have layer effects
   if (!mTarget && !haveLayerEffects &&
       gfxPrefs::Composer2DCompositionEnabled() &&
-      composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, mGeometryChanged))
+      composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot,
+          mCompositor->GetWidget(), mGeometryChanged))
   {
     LayerScope::SetHWComposed();
     if (mFPS) {
       double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
       if (gfxPrefs::LayersDrawFPS()) {
         printf_stderr("HWComposer: FPS is %g\n", fps);
       }
     }
@@ -767,17 +768,17 @@ LayerManagerComposite::Render()
     PROFILER_LABEL("LayerManagerComposite", "EndFrame",
       js::ProfileEntry::Category::GRAPHICS);
 
     mCompositor->EndFrame();
     mCompositor->SetDispAcquireFence(mRoot);
   }
 
   if (composer2D) {
-    composer2D->Render();
+    composer2D->Render(mCompositor->GetWidget());
   }
 
   mCompositor->GetWidget()->PostRender(this);
 
   RecordFrame();
 }
 
 #ifdef MOZ_WIDGET_ANDROID
--- a/gfx/layers/opengl/Composer2D.h
+++ b/gfx/layers/opengl/Composer2D.h
@@ -21,16 +21,18 @@
  *
  * Composer2D is a very simple interface to this class of hardware
  * that allows an implementation to "try rendering" with the fast
  * path.  If the given layer tree requires more generality than the
  * hardware provides, the implementation should bail and have the
  * layer manager fall back on full GPU composition.
  */
 
+class nsIWidget;
+
 namespace mozilla {
 namespace layers {
 
 class Layer;
 
 class Composer2D {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Composer2D)
 
@@ -42,23 +44,24 @@ public:
   /**
    * Return true if |aRoot| met the implementation's criteria for fast
    * composition and the render was successful.  Return false to fall
    * back on the GPU.
    *
    * Currently, when TryRender() returns true, the entire framebuffer
    * must have been rendered.
    */
-  virtual bool TryRenderWithHwc(Layer* aRoot, bool aGeometryChanged) = 0;
+  virtual bool TryRenderWithHwc(Layer* aRoot, nsIWidget* aWidget,
+                                bool aGeometryChanged) = 0;
 
   /**
    * Return true if Composer2D does composition. Return false if Composer2D
    * failed the composition.
    */
-  virtual bool Render() = 0;
+  virtual bool Render(nsIWidget* aWidget) = 0;
 
   /**
    * Return true if Composer2D has a fast composition hardware.
    * Return false if Composer2D does not have a fast composition hardware.
    */
   virtual bool HasHwc() = 0;
 };
 
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -52,16 +52,18 @@
 #include "nsCocoaFeatures.h"
 #endif
 
 #include "GeckoProfiler.h"
 
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 #include "libdisplay/GonkDisplay.h"     // for GonkDisplay
 #include <ui/Fence.h>
+#include "nsWindow.h"
+#include "nsScreenManagerGonk.h"
 #endif
 
 namespace mozilla {
 
 using namespace std;
 using namespace gfx;
 
 namespace layers {
@@ -1396,18 +1398,19 @@ CompositorOGL::SetDispAcquireFence(Layer
   // to prevent flickering and tearing.
   // DispAcquireFence is DisplaySurface's AcquireFence.
   // AcquireFence will be signaled when a buffer's content is available.
   // See Bug 974152.
 
   if (!aLayer) {
     return;
   }
-
-  RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(GetGonkDisplay()->GetPrevDispAcquireFd());
+  nsWindow* window = static_cast<nsWindow*>(mWidget);
+  RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
+      window->GetScreen()->GetPrevDispAcquireFd());
   mReleaseFenceHandle.Merge(FenceHandle(fence));
 }
 
 FenceHandle
 CompositorOGL::GetReleaseFence()
 {
   if (!mReleaseFenceHandle.IsValid()) {
     return FenceHandle();
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -28,16 +28,18 @@
 #include "mozilla/layers/PLayerTransaction.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
 #include "mozilla/StaticPtr.h"
 #include "cutils/properties.h"
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "VsyncSource.h"
+#include "nsScreenManagerGonk.h"
+#include "nsWindow.h"
 
 #if ANDROID_VERSION >= 17
 #include "libdisplay/DisplaySurface.h"
 #include "gfxPrefs.h"
 #include "nsThreadUtils.h"
 #endif
 
 #if ANDROID_VERSION >= 21
@@ -91,34 +93,31 @@ HookVsync(const struct hwc_procs* aProcs
 {
     HwcComposer2D::GetInstance()->Vsync(aDisplay, aTimestamp);
 }
 
 static void
 HookHotplug(const struct hwc_procs* aProcs, int aDisplay,
             int aConnected)
 {
-    // no op
+    HwcComposer2D::GetInstance()->Hotplug(aDisplay, aConnected);
 }
 
 static const hwc_procs_t sHWCProcs = {
     &HookInvalidate, // 1st: void (*invalidate)(...)
     &HookVsync,      // 2nd: void (*vsync)(...)
     &HookHotplug     // 3rd: void (*hotplug)(...)
 };
 #endif
 
 static StaticRefPtr<HwcComposer2D> sInstance;
 
 HwcComposer2D::HwcComposer2D()
     : mHwc(nullptr)
     , mList(nullptr)
-    , mDpy(EGL_NO_DISPLAY)
-    , mSur(EGL_NO_SURFACE)
-    , mGLContext(nullptr)
     , mMaxLayerCount(0)
     , mColorFill(false)
     , mRBSwapSupport(false)
     , mPrepared(false)
     , mHasHWVsync(false)
     , mLock("mozilla.HwcComposer2D.mLock")
 {
 #if ANDROID_VERSION >= 17
@@ -128,17 +127,18 @@ HwcComposer2D::HwcComposer2D()
     mHwc = (HwcDevice*)GetGonkDisplay()->GetHWCDevice();
     if (!mHwc) {
         LOGD("no hwc support");
         return;
     }
 
     nsIntSize screenSize;
 
-    ANativeWindow *win = GetGonkDisplay()->GetNativeWindow();
+    GonkDisplay::NativeData data = GetGonkDisplay()->GetNativeData(GonkDisplay::DISPLAY_PRIMARY);
+    ANativeWindow *win = data.mNativeWindow.get();
     win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width);
     win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height);
     mScreenRect = gfx::IntRect(gfx::IntPoint(0, 0), screenSize);
 
 #if ANDROID_VERSION >= 17
     int supported = 0;
 
     if (mHwc->query) {
@@ -243,33 +243,57 @@ HwcComposer2D::Invalidate()
         return;
     }
 
     MutexAutoLock lock(mLock);
     if (mCompositorParent) {
         mCompositorParent->ScheduleRenderOnCompositorThread();
     }
 }
+
+namespace {
+class HotplugEvent : public nsRunnable {
+public:
+    HotplugEvent(GonkDisplay::DisplayType aType, bool aConnected)
+        : mType(aType)
+        , mConnected(aConnected)
+    {
+    }
+
+    NS_IMETHOD Run()
+    {
+        nsRefPtr<nsScreenManagerGonk> screenManager =
+            nsScreenManagerGonk::GetInstance();
+        if (mConnected) {
+            screenManager->AddScreen(mType);
+        } else {
+            screenManager->RemoveScreen(mType);
+        }
+    }
+private:
+    GonkDisplay::DisplayType mType;
+    bool mConnected;
+};
+} // anonymous namespace
+
+void
+HwcComposer2D::Hotplug(int aDisplay, int aConnected)
+{
+    NS_DispatchToMainThread(new HotplugEvent(GonkDisplay::DISPLAY_EXTERNAL,
+                                             aConnected));
+}
 #endif
 
 void
 HwcComposer2D::SetCompositorParent(CompositorParent* aCompositorParent)
 {
     MutexAutoLock lock(mLock);
     mCompositorParent = aCompositorParent;
 }
 
-void
-HwcComposer2D::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext)
-{
-    mDpy = aDisplay;
-    mSur = aSurface;
-    mGLContext = aGLContext;
-}
-
 bool
 HwcComposer2D::ReallocLayerList()
 {
     int size = sizeof(HwcList) +
         ((mMaxLayerCount + LAYER_COUNT_INCREMENTS) * sizeof(HwcLayer));
 
     HwcList* listrealloc = (HwcList*)realloc(mList, size);
 
@@ -679,35 +703,35 @@ HwcComposer2D::PrepareLayerList(Layer* a
     mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData()));
     mList->numHwLayers++;
     return true;
 }
 
 
 #if ANDROID_VERSION >= 17
 bool
-HwcComposer2D::TryHwComposition()
+HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
 {
-    DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
+    DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
 
     if (!(dispSurface && dispSurface->lastHandle)) {
         LOGD("H/W Composition failed. DispSurface not initialized.");
         return false;
     }
 
     // Add FB layer
     int idx = mList->numHwLayers++;
     if (idx >= mMaxLayerCount) {
         if (!ReallocLayerList() || idx >= mMaxLayerCount) {
             LOGE("TryHwComposition failed! Could not add FB layer");
             return false;
         }
     }
 
-    Prepare(dispSurface->lastHandle, -1);
+    Prepare(dispSurface->lastHandle, -1, aScreen);
 
     /* Possible composition paths, after hwc prepare:
     1. GPU Composition
     2. BLIT Composition
     3. Full OVERLAY Composition
     4. Partial OVERLAY Composition (GPU + OVERLAY) */
 
     bool gpuComposite = false;
@@ -752,44 +776,47 @@ HwcComposer2D::TryHwComposition()
             }
         }
 
         if (gpuComposite) {
             // GPU or partial OVERLAY Composition
             return false;
         } else if (blitComposite) {
             // BLIT Composition, flip DispSurface target
-            GetGonkDisplay()->UpdateDispSurface(mDpy, mSur);
-            DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
+            GetGonkDisplay()->UpdateDispSurface(aScreen->GetDpy(), aScreen->GetSur());
+            DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
             if (!dispSurface) {
                 LOGE("H/W Composition failed. NULL DispSurface.");
                 return false;
             }
             mList->hwLayers[idx].handle = dispSurface->lastHandle;
             mList->hwLayers[idx].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
         }
     }
 
     // BLIT or full OVERLAY Composition
-    Commit();
+    Commit(aScreen);
 
-    GetGonkDisplay()->SetDispReleaseFd(mList->hwLayers[idx].releaseFenceFd);
+    DisplaySurface* displaySurface = aScreen->GetDisplaySurface();
+    displaySurface->setReleaseFenceFd(mList->hwLayers[idx].releaseFenceFd);
     mList->hwLayers[idx].releaseFenceFd = -1;
     return true;
 }
 
 bool
-HwcComposer2D::Render()
+HwcComposer2D::Render(nsIWidget* aWidget)
 {
+    nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
+
     // HWC module does not exist or mList is not created yet.
     if (!mHwc || !mList) {
-        return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
+        return GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur());
     }
 
-    DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
+    DisplaySurface* dispSurface = screen->GetDisplaySurface();
     if (!dispSurface) {
         LOGE("H/W Composition failed. DispSurface not initialized.");
         return false;
     }
 
     if (mPrepared) {
         // No mHwc prepare, if already prepared in current draw cycle
         mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle;
@@ -799,35 +826,36 @@ HwcComposer2D::Render()
         mList->numHwLayers = 2;
         mList->hwLayers[0].hints = 0;
         mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER;
         mList->hwLayers[0].flags = HWC_SKIP_LAYER;
         mList->hwLayers[0].backgroundColor = {0};
         mList->hwLayers[0].acquireFenceFd = -1;
         mList->hwLayers[0].releaseFenceFd = -1;
         mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
-        Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd());
+        Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen);
     }
 
     // GPU or partial HWC Composition
-    Commit();
+    Commit(screen);
 
-    GetGonkDisplay()->SetDispReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
+    dispSurface->setReleaseFenceFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
     mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd = -1;
     return true;
 }
 
 void
-HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence)
+HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen)
 {
     int idx = mList->numHwLayers - 1;
     const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height};
     hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
 
-    displays[HWC_DISPLAY_PRIMARY] = mList;
+    uint32_t displaytype = screen->GetDisplayType();
+    displays[displaytype] = mList;
     mList->outbufAcquireFenceFd = -1;
     mList->outbuf = nullptr;
     mList->retireFenceFd = -1;
 
     mList->hwLayers[idx].hints = 0;
     mList->hwLayers[idx].flags = 0;
     mList->hwLayers[idx].transform = 0;
     mList->hwLayers[idx].handle = dispHandle;
@@ -840,25 +868,27 @@ HwcComposer2D::Prepare(buffer_handle_t d
     mList->hwLayers[idx].acquireFenceFd = fence;
     mList->hwLayers[idx].releaseFenceFd = -1;
 #if ANDROID_VERSION >= 18
     mList->hwLayers[idx].planeAlpha = 0xFF;
 #endif
     if (mPrepared) {
         LOGE("Multiple hwc prepare calls!");
     }
+
     mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
     mPrepared = true;
 }
 
 bool
-HwcComposer2D::Commit()
+HwcComposer2D::Commit(nsScreenGonk* aScreen)
 {
     hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
-    displays[HWC_DISPLAY_PRIMARY] = mList;
+    uint32_t displaytype = aScreen->GetDisplayType();
+    displays[displaytype] = mList;
 
     for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
         mList->hwLayers[j].acquireFenceFd = -1;
         if (mHwcLayerMap.IsEmpty() ||
             (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER)) {
             continue;
         }
         LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
@@ -905,70 +935,76 @@ HwcComposer2D::Reset()
     LOGD("hwcomposer is already prepared, reset with null set");
     hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
     displays[HWC_DISPLAY_PRIMARY] = nullptr;
     mHwc->set(mHwc, HWC_DISPLAY_PRIMARY, displays);
     mPrepared = false;
 }
 #else
 bool
-HwcComposer2D::TryHwComposition()
+HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
 {
-    return !mHwc->set(mHwc, mDpy, mSur, mList);
+    return !mHwc->set(mHwc, aScreen->GetDpy(), aScreen->GetSur(), mList);
 }
 
 bool
-HwcComposer2D::Render()
+HwcComposer2D::Render(nsIWidget* aWidget)
 {
-    return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
+    nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
+
+    return GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur());
 }
 
 void
 HwcComposer2D::Reset()
 {
     mPrepared = false;
 }
 #endif
 
 bool
 HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
+                                nsIWidget* aWidget,
                                 bool aGeometryChanged)
 {
     if (!mHwc) {
         return false;
     }
 
+    nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
+
     if (mList) {
         setHwcGeometry(aGeometryChanged);
         mList->numHwLayers = 0;
         mHwcLayerMap.Clear();
     }
 
     if (mPrepared) {
         Reset();
     }
 
     // XXX: The clear() below means all rect vectors will be have to be
     // reallocated. We may want to avoid this if possible
     mVisibleRegions.clear();
 
+    mScreenRect = screen->GetNaturalBounds();
     MOZ_ASSERT(mHwcLayerMap.IsEmpty());
     if (!PrepareLayerList(aRoot,
                           mScreenRect,
                           gfx::Matrix()))
     {
         mHwcLayerMap.Clear();
         LOGD("Render aborted. Nothing was drawn to the screen");
         return false;
     }
 
     // Send data to LayerScope for debugging
     SendtoLayerScope();
 
-    if (!TryHwComposition()) {
+    if (!TryHwComposition(screen)) {
         LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
         LayerScope::CleanLayer();
         return false;
     }
 
     LOGD("Frame rendered");
     return true;
 }
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -26,16 +26,18 @@
 #include <list>
 
 #include <hardware/hwcomposer.h>
 #if ANDROID_VERSION >= 17
 #include <ui/Fence.h>
 #include <utils/Timers.h>
 #endif
 
+class nsScreenGonk;
+
 namespace mozilla {
 
 namespace gl {
     class GLContext;
 }
 
 namespace layers {
 class CompositorParent;
@@ -78,51 +80,46 @@ public:
     virtual ~HwcComposer2D();
 
     static HwcComposer2D* GetInstance();
 
     // Returns TRUE if the container has been succesfully rendered
     // Returns FALSE if the container cannot be fully rendered
     // by this composer so nothing was rendered at all
     virtual bool TryRenderWithHwc(layers::Layer* aRoot,
+                                  nsIWidget* aWidget,
                                   bool aGeometryChanged) override;
 
-    virtual bool Render() override;
+    virtual bool Render(nsIWidget* aWidget) override;
 
     virtual bool HasHwc() override { return mHwc; }
 
     bool EnableVsync(bool aEnable);
 #if ANDROID_VERSION >= 17
     bool RegisterHwcEventCallback();
     void Vsync(int aDisplay, int64_t aTimestamp);
     void Invalidate();
+    void Hotplug(int aDisplay, int aConnected);
 #endif
     void SetCompositorParent(layers::CompositorParent* aCompositorParent);
 
-    // Set EGL info of primary display. Used for BLIT Composition.
-    // XXX Add multiple displays compostion support.
-    void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext);
-
 private:
     void Reset();
-    void Prepare(buffer_handle_t dispHandle, int fence);
-    bool Commit();
-    bool TryHwComposition();
+    void Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen);
+    bool Commit(nsScreenGonk* aScreen);
+    bool TryHwComposition(nsScreenGonk* aScreen);
     bool ReallocLayerList();
     bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
           const gfx::Matrix& aParentTransform);
     void setCrop(HwcLayer* layer, hwc_rect_t srcCrop);
     void setHwcGeometry(bool aGeometryChanged);
     void SendtoLayerScope();
 
     HwcDevice*              mHwc;
     HwcList*                mList;
-    hwc_display_t           mDpy; // Store for BLIT Composition and GonkDisplayICS
-    hwc_surface_t           mSur; // Store for BLIT Composition and GonkDisplayICS
-    gl::GLContext*          mGLContext; // Store for BLIT Composition
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
     bool                    mRBSwapSupport;
     //Holds all the dynamically allocated RectVectors needed
     //to render the current frame
     std::list<RectVector>   mVisibleRegions;
     layers::FenceHandle mPrevRetireFence;
--- a/widget/gonk/libdisplay/GonkDisplay.h
+++ b/widget/gonk/libdisplay/GonkDisplay.h
@@ -12,60 +12,76 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef GONKDISPLAY_H
 #define GONKDISPLAY_H
 
 #include <system/window.h>
+#include <utils/StrongPointer.h>
 #include "mozilla/Types.h"
 
+namespace android {
+class DisplaySurface;
+class IGraphicBufferProducer;
+}
+
 namespace mozilla {
 
 typedef void * EGLDisplay;
 typedef void * EGLSurface;
 
 class MOZ_EXPORT GonkDisplay {
 public:
-    virtual ANativeWindow* GetNativeWindow() = 0;
+   /**
+    * This enum is for types of display. DISPLAY_PRIMARY refers to the default
+    * built-in display, DISPLAY_EXTERNAL refers to displays connected with
+    * HDMI, and DISPLAY_VIRTUAL are displays which makes composited output
+    * available within the system. Currently, displays of external are detected
+    * via the hotplug detection in HWC, and displays of virtual are connected
+    * via Wifi Display.
+    */
+    enum DisplayType {
+        DISPLAY_PRIMARY,
+        DISPLAY_EXTERNAL,
+        DISPLAY_VIRTUAL,
+        NUM_DISPLAY_TYPES
+    };
+
+    struct NativeData {
+        android::sp<ANativeWindow> mNativeWindow;
+#if ANDROID_VERSION >= 17
+        android::sp<android::DisplaySurface> mDisplaySurface;
+#endif
+        float mXdpi;
+    };
 
     virtual void SetEnabled(bool enabled) = 0;
 
     typedef void (*OnEnabledCallbackType)(bool enabled);
 
     virtual void OnEnabled(OnEnabledCallbackType callback) = 0;
 
     virtual void* GetHWCDevice() = 0;
 
-    virtual void* GetDispSurface() = 0;
-
     /**
      * Only GonkDisplayICS uses arguments.
      */
     virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur) = 0;
 
     virtual ANativeWindowBuffer* DequeueBuffer() = 0;
 
     virtual bool QueueBuffer(ANativeWindowBuffer* buf) = 0;
 
     virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur) = 0;
 
-    /**
-     * Set FramebufferSurface ReleaseFence's file descriptor.
-     * ReleaseFence will be signaled after the HWC has finished reading
-     * from a buffer.
-     */
-    virtual void SetDispReleaseFd(int fd) = 0;
-
-    /**
-     * Get FramebufferSurface AcquireFence's file descriptor
-     * AcquireFence will be signaled when a buffer's content is available.
-     */
-    virtual int GetPrevDispAcquireFd() = 0;
+    virtual NativeData GetNativeData(
+        GonkDisplay::DisplayType aDisplayType,
+        android::IGraphicBufferProducer* aProducer = nullptr) = 0;
 
     float xdpi;
     int32_t surfaceformat;
 };
 
 MOZ_EXPORT __attribute__ ((weak))
 GonkDisplay* GetGonkDisplay();
 
--- a/widget/gonk/libdisplay/GonkDisplayICS.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayICS.cpp
@@ -18,16 +18,17 @@
 
 #include <hardware/hardware.h>
 #include <hardware/gralloc.h>
 #include <hardware/hwcomposer.h>
 #include <hardware_legacy/power.h>
 #include <cutils/log.h>
 #include <fcntl.h>
 
+#include "mozilla/Assertions.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/FileUtils.h"
 
 #include "BootAnimation.h"
 
 using namespace android;
 
 
@@ -134,23 +135,16 @@ GonkDisplayICS::GonkDisplayICS()
 }
 
 GonkDisplayICS::~GonkDisplayICS()
 {
     if (mHwc)
         hwc_close(mHwc);
 }
 
-ANativeWindow*
-GonkDisplayICS::GetNativeWindow()
-{
-    StopBootAnimation();
-    return static_cast<ANativeWindow *>(mFBSurface.get());
-}
-
 void
 GonkDisplayICS::SetEnabled(bool enabled)
 {
     set_screen_state(enabled);
 }
 
 void
 GonkDisplayICS::OnEnabled(OnEnabledCallbackType callback)
@@ -202,24 +196,37 @@ GonkDisplayICS::QueueBuffer(ANativeWindo
 {
     ANativeWindow *window = static_cast<ANativeWindow *>(mFBSurface.get());
     return !window->queueBuffer(window, buf);
 }
 
 void
 GonkDisplayICS::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
 {
-    eglSwapBuffers(dpy, sur);
 }
 
 void
 GonkDisplayICS::SetDispReleaseFd(int fd)
 {
 }
 
+GonkDisplay::NativeData
+GonkDisplayICS::GetNativeData(GonkDisplay::DisplayType aDisplayType,
+                              android::IGraphicBufferProducer* aProducer)
+{
+    MOZ_ASSERT(aDisplayType == DISPLAY_PRIMARY, "ICS gonk supports primary display only.");
+
+    NativeData data;
+    StopBootAnimation();
+    data.mNativeWindow = static_cast<ANativeWindow *>(mFBSurface.get());
+    data.mXdpi = xdpi;
+
+    return data;
+}
+
 __attribute__ ((visibility ("default")))
 GonkDisplay*
 GetGonkDisplay()
 {
     if (!sGonkDisplay)
         sGonkDisplay = new GonkDisplayICS();
     return sGonkDisplay;
 }
--- a/widget/gonk/libdisplay/GonkDisplayICS.h
+++ b/widget/gonk/libdisplay/GonkDisplayICS.h
@@ -18,51 +18,52 @@
 
 #include <string.h>
 
 #include "GonkDisplay.h"
 #include "ui/FramebufferNativeWindow.h"
 #include "hardware/hwcomposer.h"
 #include "utils/RefBase.h"
 
+namespace android {
+class IGraphicBufferProducer;
+}
+
 namespace mozilla {
 
 class MOZ_EXPORT GonkDisplayICS : public GonkDisplay {
 public:
     GonkDisplayICS();
     ~GonkDisplayICS();
 
-    virtual ANativeWindow* GetNativeWindow();
-
     virtual void SetEnabled(bool enabled);
 
     virtual void OnEnabled(OnEnabledCallbackType callback);
 
     virtual void* GetHWCDevice();
 
-    virtual void* GetDispSurface()
-    {
-        return nullptr;
-    }
-
     virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur);
 
     virtual ANativeWindowBuffer* DequeueBuffer();
 
     virtual bool QueueBuffer(ANativeWindowBuffer* handle);
 
     virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur);
 
     virtual void SetDispReleaseFd(int fd);
 
     virtual int GetPrevDispAcquireFd()
     {
         return -1;
     }
 
+    virtual NativeData GetNativeData(
+        GonkDisplay::DisplayType aDisplayType,
+        android::IGraphicBufferProducer* aProducer = nullptr);
+
 private:
     hw_module_t const*        mModule;
     hwc_composer_device_t*    mHwc;
     android::sp<android::FramebufferNativeWindow> mFBSurface;
 };
 
 }
 
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp
@@ -21,21 +21,24 @@
 #include <gui/GraphicBufferAlloc.h>
 #endif
 
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 #include <hardware/power.h>
 #include <suspend/autosuspend.h>
 
+#include "BootAnimation.h"
 #include "FramebufferSurface.h"
 #if ANDROID_VERSION == 17
 #include "GraphicBufferAlloc.h"
 #endif
-#include "BootAnimation.h"
+#include "mozilla/Assertions.h"
+
+#define DEFAULT_XDPI 75.0
 
 using namespace android;
 
 namespace mozilla {
 
 static GonkDisplayJB* sGonkDisplay = nullptr;
 
 GonkDisplayJB::GonkDisplayJB()
@@ -103,38 +106,30 @@ GonkDisplayJB::GonkDisplayJB()
     err = hw_get_module(POWER_HARDWARE_MODULE_ID,
                                            (hw_module_t const**)&mPowerModule);
     if (!err)
         mPowerModule->init(mPowerModule);
     ALOGW_IF(err, "Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
 
     mAlloc = new GraphicBufferAlloc();
 
-    CreateSurface(mSTClient, mDispSurface);
+    CreateSurface(mSTClient, mDispSurface, mWidth, mHeight);
 
     mList = (hwc_display_contents_1_t *)calloc(1, sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
 
     uint32_t usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
     if (mFBDevice) {
         // If device uses fb, they can not use single buffer for boot animation
         mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2);
         mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, usage);
     } else if (mHwc) {
-#if ANDROID_VERSION >= 21
-        if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
-            mHwc->setPowerMode(mHwc, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
-        } else {
-            mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
-        }
-#else
-        mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
-#endif
+        PowerOnDisplay(HWC_DISPLAY_PRIMARY);
         // For devices w/ hwc v1.0 or no hwc, this buffer can not be created,
         // only create this buffer for devices w/ hwc version > 1.0.
-        CreateSurface(mBootAnimSTClient, mBootAnimDispSurface);
+        CreateSurface(mBootAnimSTClient, mBootAnimDispSurface, mWidth, mHeight);
     }
 
     ALOGI("Starting bootanimation with (%d) format framebuffer", surfaceformat);
     StartBootAnimation();
 }
 
 GonkDisplayJB::~GonkDisplayJB()
 {
@@ -142,50 +137,43 @@ GonkDisplayJB::~GonkDisplayJB()
         hwc_close_1(mHwc);
     if (mFBDevice)
         framebuffer_close(mFBDevice);
     free(mList);
 }
 
 void
 GonkDisplayJB::CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
-                             android::sp<android::DisplaySurface>& aDisplaySurface)
+                             android::sp<android::DisplaySurface>& aDisplaySurface,
+                             uint32_t aWidth, uint32_t aHeight)
 {
 #if ANDROID_VERSION >= 21
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
     BufferQueue::createBufferQueue(&producer, &consumer, mAlloc);
 #elif ANDROID_VERSION >= 19
     sp<BufferQueue> consumer = new BufferQueue(mAlloc);
     sp<IGraphicBufferProducer> producer = consumer;
 #elif ANDROID_VERSION >= 18
     sp<BufferQueue> consumer = new BufferQueue(true, mAlloc);
     sp<IGraphicBufferProducer> producer = consumer;
 #else
     sp<BufferQueue> consumer = new BufferQueue(true, mAlloc);
 #endif
 
-    aDisplaySurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, consumer);
+    aDisplaySurface = new FramebufferSurface(0, aWidth, aHeight, surfaceformat, consumer);
 
 #if ANDROID_VERSION == 17
     aNativeWindow = new SurfaceTextureClient(
         static_cast<sp<ISurfaceTexture>>(aDisplaySurface->getBufferQueue()));
 #else
     aNativeWindow = new Surface(producer);
 #endif
 }
 
-ANativeWindow*
-GonkDisplayJB::GetNativeWindow()
-{
-    StopBootAnim();
-
-    return mSTClient.get();
-}
-
 void
 GonkDisplayJB::SetEnabled(bool enabled)
 {
     if (enabled) {
         autosuspend_disable();
         mPowerModule->setInteractive(mPowerModule, true);
     }
 
@@ -229,22 +217,16 @@ GonkDisplayJB::OnEnabled(OnEnabledCallba
 }
 
 void*
 GonkDisplayJB::GetHWCDevice()
 {
     return mHwc;
 }
 
-void*
-GonkDisplayJB::GetDispSurface()
-{
-    return mDispSurface.get();
-}
-
 bool
 GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
 {
     StopBootAnim();
 
     // Should be called when composition rendering is complete for a frame.
     // Only HWC v1.0 needs this call.
     // HWC > v1.0 case, do not call compositionComplete().
@@ -359,37 +341,76 @@ void
 GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
 {
     StopBootAnim();
 
     eglSwapBuffers(dpy, sur);
 }
 
 void
-GonkDisplayJB::SetDispReleaseFd(int fd)
-{
-    mDispSurface->setReleaseFenceFd(fd);
-}
-
-int
-GonkDisplayJB::GetPrevDispAcquireFd()
-{
-    return mDispSurface->GetPrevDispAcquireFd();
-}
-
-void
 GonkDisplayJB::StopBootAnim()
 {
     StopBootAnimation();
     if (mBootAnimSTClient.get()) {
         mBootAnimSTClient = nullptr;
         mBootAnimDispSurface = nullptr;
     }
 }
 
+void
+GonkDisplayJB::PowerOnDisplay(int aDpy)
+{
+    MOZ_ASSERT(mHwc);;
+#if ANDROID_VERSION >= 21
+    if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
+        mHwc->setPowerMode(mHwc, aDpy, HWC_POWER_MODE_NORMAL);
+    } else {
+        mHwc->blank(mHwc, aDpy, 0);
+    }
+#else
+    mHwc->blank(mHwc, aDpy, 0);
+#endif
+}
+
+GonkDisplay::NativeData
+GonkDisplayJB::GetNativeData(GonkDisplay::DisplayType aDisplayType,
+                             android::IGraphicBufferProducer* aProducer)
+{
+    NativeData data;
+
+    if (aDisplayType == DISPLAY_PRIMARY) {
+        StopBootAnim();
+        data.mNativeWindow = mSTClient;
+        data.mDisplaySurface = mDispSurface;
+        data.mXdpi = xdpi;
+    } else if (aDisplayType == DISPLAY_EXTERNAL) {
+        int32_t values[3];
+        const uint32_t attrs[] = {
+            HWC_DISPLAY_WIDTH,
+            HWC_DISPLAY_HEIGHT,
+            HWC_DISPLAY_DPI_X,
+            HWC_DISPLAY_NO_ATTRIBUTE
+        };
+        mHwc->getDisplayAttributes(mHwc, aDisplayType, 0, attrs, values);
+        int width = values[0];
+        int height = values[1];
+        // FIXME!! values[2] returns 0 for external display, which doesn't
+        // sound right, Bug 1169176 is the follow-up bug for this issue.
+        data.mXdpi = values[2] ? values[2] / 1000.f : DEFAULT_XDPI;
+        PowerOnDisplay(HWC_DISPLAY_EXTERNAL);
+        CreateSurface(data.mNativeWindow, data.mDisplaySurface, width, height);
+    } else if (aDisplayType == DISPLAY_VIRTUAL) {
+        // TODO: Bug 1161874 (the support of WifiDisplay) should fill up the
+        // implementation of virtual display.
+        MOZ_CRASH("Display type of virtual is not supported yet.");
+    }
+
+    return data;
+}
+
 __attribute__ ((visibility ("default")))
 GonkDisplay*
 GetGonkDisplay()
 {
     if (!sGonkDisplay)
         sGonkDisplay = new GonkDisplayJB();
     return sGonkDisplay;
 }
--- a/widget/gonk/libdisplay/GonkDisplayJB.h
+++ b/widget/gonk/libdisplay/GonkDisplayJB.h
@@ -25,44 +25,42 @@
 
 namespace mozilla {
 
 class MOZ_EXPORT GonkDisplayJB : public GonkDisplay {
 public:
     GonkDisplayJB();
     ~GonkDisplayJB();
 
-    virtual ANativeWindow* GetNativeWindow();
-
     virtual void SetEnabled(bool enabled);
 
     virtual void OnEnabled(OnEnabledCallbackType callback);
 
     virtual void* GetHWCDevice();
 
-    virtual void* GetDispSurface();
-
     virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur);
 
     virtual ANativeWindowBuffer* DequeueBuffer();
 
     virtual bool QueueBuffer(ANativeWindowBuffer* buf);
 
     virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur);
 
-    virtual void SetDispReleaseFd(int fd);
+    bool Post(buffer_handle_t buf, int fence);
 
-    virtual int GetPrevDispAcquireFd();
-
-    bool Post(buffer_handle_t buf, int fence);
+    virtual NativeData GetNativeData(
+        GonkDisplay::DisplayType aDisplayType,
+        android::IGraphicBufferProducer* aProducer = nullptr);
 
 private:
     void StopBootAnim();
     void CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
-                       android::sp<android::DisplaySurface>& aDisplaySurface);
+                       android::sp<android::DisplaySurface>& aDisplaySurface,
+                       uint32_t aWidth, uint32_t aHeight);
+    void PowerOnDisplay(int aDpy);
 
     hw_module_t const*        mModule;
     hw_module_t const*        mFBModule;
     hwc_composer_device_1_t*  mHwc;
     framebuffer_device_t*     mFBDevice;
     power_module_t*           mPowerModule;
     android::sp<android::DisplaySurface> mDispSurface;
     android::sp<ANativeWindow> mSTClient;
--- a/widget/gonk/nsScreenManagerGonk.cpp
+++ b/widget/gonk/nsScreenManagerGonk.cpp
@@ -14,30 +14,33 @@
  */
 
 #include "android/log.h"
 #include "GLContext.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/Hal.h"
 #include "libdisplay/GonkDisplay.h"
-#include "libdisplay/DisplaySurface.h"
 #include "nsScreenManagerGonk.h"
 #include "nsThreadUtils.h"
 #include "HwcComposer2D.h"
 #include "VsyncSource.h"
 #include "nsWindow.h"
 #include "mozilla/Services.h"
 #include "mozilla/ProcessPriorityManager.h"
 #include "nsIdleService.h"
 #include "nsIObserverService.h"
 #include "nsAppShell.h"
 #include "nsTArray.h"
 #include "pixelflinger/format.h"
-#include "cutils/properties.h"
+#include "nsIDisplayInfo.h"
+
+#if ANDROID_VERSION >= 17
+#include "libdisplay/DisplaySurface.h"
+#endif
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "nsScreenGonk" , ## args)
 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "nsScreenGonk", ## args)
 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "nsScreenGonk", ## args)
 
 using namespace mozilla;
 using namespace mozilla::hal;
 using namespace mozilla::gfx;
@@ -98,49 +101,57 @@ SurfaceFormatToColorDepth(int32_t aSurfa
     case GGL_PIXEL_FORMAT_RGBA_8888:
         return 32;
     }
     return 24; // GGL_PIXEL_FORMAT_RGBX_8888
 }
 
 // nsScreenGonk.cpp
 
-nsScreenGonk::nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow)
+nsScreenGonk::nsScreenGonk(uint32_t aId,
+                           GonkDisplay::DisplayType aDisplayType,
+                           const GonkDisplay::NativeData& aNativeData)
     : mId(aId)
-    , mNativeWindow(aNativeWindow)
+    , mNativeWindow(aNativeData.mNativeWindow)
+    , mDpi(aNativeData.mXdpi)
     , mScreenRotation(nsIScreen::ROTATION_0_DEG)
     , mPhysicalScreenRotation(nsIScreen::ROTATION_0_DEG)
+#if ANDROID_VERSION >= 17
+    , mDisplaySurface(aNativeData.mDisplaySurface)
+#endif
+    , mDisplayType(aDisplayType)
+    , mDpy(EGL_NO_DISPLAY)
+    , mSur(EGL_NO_SURFACE)
+    , mGLContext(nullptr)
 {
-    int surfaceFormat;
     if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) ||
         mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) ||
-        mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &surfaceFormat)) {
+        mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &mSurfaceFormat)) {
         NS_RUNTIMEABORT("Failed to get native window size, aborting...");
     }
 
     mNaturalBounds = mVirtualBounds;
 
     if (IsPrimaryScreen()) {
         char propValue[PROPERTY_VALUE_MAX];
         property_get("ro.sf.hwrotation", propValue, "0");
         mPhysicalScreenRotation = atoi(propValue) / 90;
     }
 
-    mDpi = GetGonkDisplay()->xdpi;
-    mColorDepth = SurfaceFormatToColorDepth(surfaceFormat);
+    mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat);
 }
 
 nsScreenGonk::~nsScreenGonk()
 {
 }
 
 bool
 nsScreenGonk::IsPrimaryScreen()
 {
-    return nsScreenManagerGonk::PRIMARY_SCREEN_ID == mId;
+    return mDisplayType == GonkDisplay::DISPLAY_PRIMARY;
 }
 
 NS_IMETHODIMP
 nsScreenGonk::GetId(uint32_t *outId)
 {
     *outId = mId;
     return NS_OK;
 }
@@ -201,16 +212,22 @@ nsScreenGonk::GetRotation(uint32_t* aRot
 }
 
 float
 nsScreenGonk::GetDpi()
 {
     return mDpi;
 }
 
+int32_t
+nsScreenGonk::GetSurfaceFormat()
+{
+    return mSurfaceFormat;
+}
+
 ANativeWindow*
 nsScreenGonk::GetNativeWindow()
 {
     return mNativeWindow.get();
 }
 
 NS_IMETHODIMP
 nsScreenGonk::SetRotation(uint32_t aRotation)
@@ -233,18 +250,18 @@ nsScreenGonk::SetRotation(uint32_t aRota
     } else {
         mVirtualBounds = mNaturalBounds;
     }
 
     nsAppShell::NotifyScreenRotation();
 
     for (unsigned int i = 0; i < mTopWindows.Length(); i++) {
         mTopWindows[i]->Resize(mVirtualBounds.width,
-                            mVirtualBounds.height,
-                            true);
+                               mVirtualBounds.height,
+                               true);
     }
 
     return NS_OK;
 }
 
 nsIntRect
 nsScreenGonk::GetNaturalBounds()
 {
@@ -309,16 +326,60 @@ nsScreenGonk::UnregisterWindow(nsWindow*
 
 void
 nsScreenGonk::BringToTop(nsWindow* aWindow)
 {
     mTopWindows.RemoveElement(aWindow);
     mTopWindows.InsertElementAt(0, aWindow);
 }
 
+#if ANDROID_VERSION >= 17
+android::DisplaySurface*
+nsScreenGonk::GetDisplaySurface()
+{
+    return mDisplaySurface.get();
+}
+
+int
+nsScreenGonk::GetPrevDispAcquireFd()
+{
+    if (!mDisplaySurface.get()) {
+        return -1;
+    }
+    return mDisplaySurface->GetPrevDispAcquireFd();
+}
+#endif
+
+GonkDisplay::DisplayType
+nsScreenGonk::GetDisplayType()
+{
+    return mDisplayType;
+}
+
+void
+nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
+                         gl::GLContext* aGLContext)
+{
+    mDpy = aDisplay;
+    mSur = aSurface;
+    mGLContext = aGLContext;
+}
+
+hwc_display_t
+nsScreenGonk::GetDpy()
+{
+    return mDpy;
+}
+
+hwc_surface_t
+nsScreenGonk::GetSur()
+{
+    return mSur;
+}
+
 NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
 
 nsScreenManagerGonk::nsScreenManagerGonk()
     : mInitialized(false)
 {
 }
 
 nsScreenManagerGonk::~nsScreenManagerGonk()
@@ -352,17 +413,17 @@ nsScreenManagerGonk::Initialize()
     if (mInitialized) {
         return;
     }
 
     mScreenOnEvent = new ScreenOnOffEvent(true);
     mScreenOffEvent = new ScreenOnOffEvent(false);
     GetGonkDisplay()->OnEnabled(displayEnabledCallback);
 
-    AddScreen(PRIMARY_SCREEN_TYPE);
+    AddScreen(GonkDisplay::DISPLAY_PRIMARY);
 
     nsAppShell::NotifyScreenInitialized();
     mInitialized = true;
 }
 
 void
 nsScreenManagerGonk::DisplayEnabled(bool aEnabled)
 {
@@ -453,42 +514,136 @@ nsScreenManagerGonk::VsyncControl(bool a
     if (aEnabled) {
         display.EnableVsync();
     } else {
         display.DisableVsync();
     }
 }
 
 uint32_t
-nsScreenManagerGonk::GetIdFromType(uint32_t aDisplayType)
+nsScreenManagerGonk::GetIdFromType(GonkDisplay::DisplayType aDisplayType)
 {
     // This is the only place where we make the assumption that
     // display type is equivalent to screen id.
 
     // Bug 1138287 will address the conversion from type to id.
     return aDisplayType;
 }
 
-void
-nsScreenManagerGonk::AddScreen(uint32_t aDisplayType)
+bool
+nsScreenManagerGonk::IsScreenConnected(uint32_t aId)
 {
-    // We currently only support adding primary screen.
-    MOZ_ASSERT(PRIMARY_SCREEN_TYPE == aDisplayType);
+    for (size_t i = 0; i < mScreens.Length(); ++i) {
+        if (mScreens[i]->GetId() == aId) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+namespace {
+
+// A concrete class as a subject for 'display-changed' observer event.
+class DisplayInfo : public nsIDisplayInfo {
+public:
+    NS_DECL_ISUPPORTS
+
+    DisplayInfo(uint32_t aId, bool aConnected)
+        : mId(aId)
+        , mConnected(aConnected)
+    {
+    }
+
+    NS_IMETHODIMP GetId(int32_t *aId)
+    {
+        *aId = mId;
+        return NS_OK;
+    }
+
+    NS_IMETHODIMP GetConnected(bool *aConnected)
+    {
+        *aConnected = mConnected;
+        return NS_OK;
+    }
+
+private:
+    virtual ~DisplayInfo() {}
+
+    uint32_t mId;
+    bool mConnected;
+};
+
+NS_IMPL_ISUPPORTS(DisplayInfo, nsIDisplayInfo, nsISupports)
+
+class NotifyTask : public nsRunnable {
+public:
+    NotifyTask(uint32_t aId, bool aConnected)
+        : mDisplayInfo(new DisplayInfo(aId, aConnected))
+    {
+    }
+
+    NS_IMETHOD Run()
+    {
+        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+        if (os) {
+          os->NotifyObservers(mDisplayInfo, "display-changed", nullptr);
+        }
+
+        return NS_OK;
+    }
+private:
+    nsRefPtr<DisplayInfo> mDisplayInfo;
+};
+
+void
+NotifyDisplayChange(uint32_t aId, bool aConnected)
+{
+    NS_DispatchToMainThread(new NotifyTask(aId, aConnected));
+}
+
+} // end of unnamed namespace.
+
+nsresult
+nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
+                               android::IGraphicBufferProducer* aProducer)
+{
+    MOZ_ASSERT(NS_IsMainThread());
+
+    NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
+                   NS_ERROR_FAILURE);
 
     uint32_t id = GetIdFromType(aDisplayType);
+    NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE);
 
-    ANativeWindow* win = GetGonkDisplay()->GetNativeWindow();
-    nsScreenGonk* screen = new nsScreenGonk(id, win);
+    GonkDisplay::NativeData nativeData =
+        GetGonkDisplay()->GetNativeData(aDisplayType, aProducer);
+    nsScreenGonk* screen = new nsScreenGonk(id, aDisplayType, nativeData);
 
     mScreens.AppendElement(screen);
+
+    NotifyDisplayChange(id, true);
+
+    return NS_OK;
 }
 
-void
-nsScreenManagerGonk::RemoveScreen(uint32_t aDisplayType)
+nsresult
+nsScreenManagerGonk::RemoveScreen(GonkDisplay::DisplayType aDisplayType)
 {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
+                   NS_ERROR_FAILURE);
+
     uint32_t screenId = GetIdFromType(aDisplayType);
+    NS_ENSURE_TRUE(IsScreenConnected(screenId), NS_ERROR_FAILURE);
+
     for (size_t i = 0; i < mScreens.Length(); i++) {
         if (mScreens[i]->GetId() == screenId) {
             mScreens.RemoveElementAt(i);
             break;
         }
     }
+
+    NotifyDisplayChange(screenId, false);
+
+    return NS_OK;
 }
--- a/widget/gonk/nsScreenManagerGonk.h
+++ b/widget/gonk/nsScreenManagerGonk.h
@@ -13,101 +13,136 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 #ifndef nsScreenManagerGonk_h___
 #define nsScreenManagerGonk_h___
 
 #include "mozilla/Hal.h"
+
+#include "cutils/properties.h"
+#include "hardware/hwcomposer.h"
+#include "libdisplay/GonkDisplay.h"
+#include "nsBaseScreen.h"
 #include "nsCOMPtr.h"
-
-#include "nsBaseScreen.h"
 #include "nsIScreenManager.h"
 
 class nsRunnable;
 class nsWindow;
 
+namespace android {
+    class DisplaySurface;
+    class IGraphicBufferProducer;
+};
+
+namespace mozilla {
+namespace gl {
+    class GLContext;
+}
+}
+
 class nsScreenGonk : public nsBaseScreen
 {
     typedef mozilla::hal::ScreenConfiguration ScreenConfiguration;
+    typedef mozilla::GonkDisplay GonkDisplay;
 
 public:
-    nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow);
+    nsScreenGonk(uint32_t aId,
+                 GonkDisplay::DisplayType aDisplayType,
+                 const GonkDisplay::NativeData& aNativeData);
 
     ~nsScreenGonk();
 
     NS_IMETHOD GetId(uint32_t* aId);
     NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
     NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight);
     NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth);
     NS_IMETHOD GetColorDepth(int32_t* aColorDepth);
     NS_IMETHOD GetRotation(uint32_t* aRotation);
     NS_IMETHOD SetRotation(uint32_t  aRotation);
 
     uint32_t GetId();
     nsIntRect GetRect();
     float GetDpi();
+    int32_t GetSurfaceFormat();
     ANativeWindow* GetNativeWindow();
     nsIntRect GetNaturalBounds();
     uint32_t EffectiveScreenRotation();
     ScreenConfiguration GetConfiguration();
     bool IsPrimaryScreen();
 
+#if ANDROID_VERSION >= 17
+    android::DisplaySurface* GetDisplaySurface();
+    int GetPrevDispAcquireFd();
+#endif
+    GonkDisplay::DisplayType GetDisplayType();
+
     void RegisterWindow(nsWindow* aWindow);
     void UnregisterWindow(nsWindow* aWindow);
     void BringToTop(nsWindow* aWindow);
 
     const nsTArray<nsWindow*>& GetTopWindows() const
     {
         return mTopWindows;
     }
 
+    // Set EGL info of primary display. Used for BLIT Composition.
+    void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
+                    mozilla::gl::GLContext* aGLContext);
+    hwc_display_t GetDpy();
+    hwc_surface_t GetSur();
+
 protected:
     uint32_t mId;
     int32_t mColorDepth;
     android::sp<ANativeWindow> mNativeWindow;
     float mDpi;
+    int32_t mSurfaceFormat;
     nsIntRect mNaturalBounds; // Screen bounds w/o rotation taken into account.
     nsIntRect mVirtualBounds; // Screen bounds w/ rotation taken into account.
     uint32_t mScreenRotation;
     uint32_t mPhysicalScreenRotation;
     nsTArray<nsWindow*> mTopWindows;
+#if ANDROID_VERSION >= 17
+    android::sp<android::DisplaySurface> mDisplaySurface;
+#endif
+    GonkDisplay::DisplayType mDisplayType;
+    hwc_display_t mDpy; // Store for BLIT Composition and GonkDisplayICS
+    hwc_surface_t mSur; // Store for BLIT Composition and GonkDisplayICS
+    mozilla::gl::GLContext* mGLContext; // Store for BLIT Composition
 };
 
 class nsScreenManagerGonk final : public nsIScreenManager
 {
 public:
-    enum {
-        // TODO: Bug 1138287 will define more screen/display types.
-        PRIMARY_SCREEN_TYPE = 0,
-
-        // TODO: Maintain a mapping from type to id dynamically.
-        PRIMARY_SCREEN_ID = 0,
-    };
+    typedef mozilla::GonkDisplay GonkDisplay;
 
 public:
     nsScreenManagerGonk();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCREENMANAGER
 
     static already_AddRefed<nsScreenManagerGonk> GetInstance();
     static already_AddRefed<nsScreenGonk> GetPrimaryScreen();
 
     void Initialize();
     void DisplayEnabled(bool aEnabled);
 
-    void AddScreen(uint32_t aDisplayType);
-    void RemoveScreen(uint32_t aDisplayType);
+    nsresult AddScreen(GonkDisplay::DisplayType aDisplayType,
+                       android::IGraphicBufferProducer* aProducer = nullptr);
+
+    nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);
 
 protected:
     ~nsScreenManagerGonk();
     void VsyncControl(bool aEnabled);
-    uint32_t GetIdFromType(uint32_t aDisplayType);
+    uint32_t GetIdFromType(GonkDisplay::DisplayType aDisplayType);
+    bool IsScreenConnected(uint32_t aId);
 
     bool mInitialized;
     nsTArray<nsRefPtr<nsScreenGonk>> mScreens;
     nsRefPtr<nsRunnable> mScreenOnEvent;
     nsRefPtr<nsRunnable> mScreenOffEvent;
 };
 
 #endif /* nsScreenManagerGonk_h___ */
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -13,17 +13,16 @@
  * limitations under the License.
  */
 
 #include "mozilla/DebugOnly.h"
 
 #include <fcntl.h>
 
 #include "android/log.h"
-
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxUtils.h"
@@ -40,18 +39,16 @@
 #include "BasicLayers.h"
 #include "libdisplay/GonkDisplay.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorParent.h"
-#include "mozilla/layers/InputAPZContext.h"
-#include "mozilla/MouseEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "HwcComposer2D.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
 
 #define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
@@ -544,21 +541,19 @@ nsWindow::GetNativeData(uint32_t aDataTy
 
 void
 nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
 {
     switch (aDataType) {
     case NS_NATIVE_OPENGL_CONTEXT:
         // Called after primary display's GLContextEGL creation.
         GLContext* context = reinterpret_cast<GLContext*>(aVal);
-
-        HwcComposer2D* hwc = HwcComposer2D::GetInstance();
-        hwc->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
-                        GLContextEGL::Cast(context)->GetEGLSurface(),
-                        context);
+        mScreen->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
+                            GLContextEGL::Cast(context)->GetEGLSurface(),
+                            context);
         return;
     }
 }
 
 NS_IMETHODIMP
 nsWindow::DispatchEvent(WidgetGUIEvent* aEvent, nsEventStatus& aStatus)
 {
     if (mWidgetListener) {
@@ -805,26 +800,32 @@ nsWindow::GetGLFrameBufferFormat()
 }
 
 nsIntRect
 nsWindow::GetNaturalBounds()
 {
     return mScreen->GetNaturalBounds();
 }
 
+nsScreenGonk*
+nsWindow::GetScreen()
+{
+    return mScreen;
+}
+
 bool
 nsWindow::NeedsPaint()
 {
   if (!mLayerManager) {
     return false;
   }
   return nsIWidget::NeedsPaint();
 }
 
 Composer2D*
 nsWindow::GetComposer2D()
 {
-    if (!mScreen->IsPrimaryScreen()) {
+    if (mScreen->GetDisplayType() == GonkDisplay::DISPLAY_VIRTUAL) {
         return nullptr;
     }
 
     return HwcComposer2D::GetInstance();
 }
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -118,16 +118,18 @@ public:
 
     virtual nsIntRect GetNaturalBounds() override;
     virtual bool NeedsPaint();
 
     virtual Composer2D* GetComposer2D() override;
 
     void ConfigureAPZControllerThread() override;
 
+    nsScreenGonk* GetScreen();
+
 protected:
     nsWindow* mParent;
     bool mVisible;
     InputContext mInputContext;
     nsCOMPtr<nsIIdleServiceInternal> mIdleService;
     // If we're using a BasicCompositor, these fields are temporarily
     // set during frame composition.  They wrap the hardware
     // framebuffer.
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -61,16 +61,17 @@ XPIDL_SOURCES += [
     'nsIBaseWindow.idl',
     'nsIBidiKeyboard.idl',
     'nsIClipboard.idl',
     'nsIClipboardDragDropHookList.idl',
     'nsIClipboardDragDropHooks.idl',
     'nsIClipboardHelper.idl',
     'nsIClipboardOwner.idl',
     'nsIColorPicker.idl',
+    'nsIDisplayInfo.idl',
     'nsIDragService.idl',
     'nsIDragSession.idl',
     'nsIFilePicker.idl',
     'nsIFormatConverter.idl',
     'nsIGfxInfo.idl',
     'nsIGfxInfoDebug.idl',
     'nsIIdleService.idl',
     'nsIIdleServiceInternal.idl',
new file mode 100644
--- /dev/null
+++ b/widget/nsIDisplayInfo.idl
@@ -0,0 +1,14 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(615bc23d-6346-4b15-9c10-add002f140b6)]
+interface nsIDisplayInfo : nsISupports
+{
+  readonly attribute long id;
+  readonly attribute boolean connected;
+};