OSDN Git Service

Reshuffle FramebufferSurface
authorAndy McFadden <fadden@android.com>
Mon, 10 Sep 2012 21:08:09 +0000 (14:08 -0700)
committerAndy McFadden <fadden@android.com>
Tue, 11 Sep 2012 16:31:34 +0000 (09:31 -0700)
FramebufferSurface no longer speaks directly to the FB HAL.  Now
everything goes through HWComposer (which may or may not be
connected to a hardware composer).

Added display index arg to some query methods.

Change-Id: Id3e157d2d4e3555d33afbb703e518b6e92e2d6d5

services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
services/surfaceflinger/DisplayHardware/FramebufferSurface.h
services/surfaceflinger/DisplayHardware/HWComposer.cpp
services/surfaceflinger/DisplayHardware/HWComposer.h
services/surfaceflinger/Layer.cpp
services/surfaceflinger/SurfaceFlinger.cpp

index f85f604..5fba3f6 100644 (file)
 #include <ui/GraphicBuffer.h>
 
 #include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/HWComposer.h"
 
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-sp<FramebufferSurface> FramebufferSurface::create() {
-    sp<FramebufferSurface> result = new FramebufferSurface();
-    if (result->fbDev == NULL) {
-        result = NULL;
-    }
-    return result;
-}
-
-// ----------------------------------------------------------------------------
-
 class GraphicBufferAlloc : public BnGraphicBufferAlloc {
 public:
     GraphicBufferAlloc() { };
@@ -66,36 +57,21 @@ public:
  *
  */
 
-FramebufferSurface::FramebufferSurface():
+FramebufferSurface::FramebufferSurface(HWComposer& hwc) :
     ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())),
-    fbDev(0),
     mCurrentBufferSlot(-1),
-    mCurrentBuffer(0)
+    mCurrentBuffer(0),
+    mHwc(hwc)
 {
-    hw_module_t const* module;
-
-    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
-        int stride;
-        int err;
-        int i;
-        err = framebuffer_open(module, &fbDev);
-        ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
-
-        // bail out if we can't initialize the modules
-        if (!fbDev)
-            return;
-
-        mName = "FramebufferSurface";
-        mBufferQueue->setConsumerName(mName);
-        mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
-                GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER);
-        mBufferQueue->setDefaultBufferFormat(fbDev->format);
-        mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height);
-        mBufferQueue->setSynchronousMode(true);
-        mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
-    } else {
-        ALOGE("Couldn't get gralloc module");
-    }
+    mName = "FramebufferSurface";
+    mBufferQueue->setConsumerName(mName);
+    mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
+                                       GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER);
+    mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(HWC_DISPLAY_PRIMARY));
+    mBufferQueue->setDefaultBufferSize(mHwc.getResolutionX(HWC_DISPLAY_PRIMARY),
+                                       mHwc.getResolutionY(HWC_DISPLAY_PRIMARY));
+    mBufferQueue->setSynchronousMode(true);
+    mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
 }
 
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
@@ -145,12 +121,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
     return NO_ERROR;
 }
 
-FramebufferSurface::~FramebufferSurface() {
-    if (fbDev) {
-        framebuffer_close(fbDev);
-    }
-}
-
+// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
 void FramebufferSurface::onFrameAvailable() {
     // XXX: The following code is here temporarily as part of the transition
     // away from the framebuffer HAL.
@@ -161,7 +132,7 @@ void FramebufferSurface::onFrameAvailable() {
                 strerror(-err), err);
         return;
     }
-    err = fbDev->post(fbDev, buf->handle);
+    err = mHwc.fbPost(buf->handle);
     if (err != NO_ERROR) {
         ALOGE("error posting framebuffer: %d", err);
     }
@@ -181,19 +152,11 @@ status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
 
 status_t FramebufferSurface::compositionComplete()
 {
-    if (fbDev->compositionComplete) {
-        return fbDev->compositionComplete(fbDev);
-    }
-    return INVALID_OPERATION;
+    return mHwc.fbCompositionComplete();
 }
 
 void FramebufferSurface::dump(String8& result) {
-    if (fbDev->common.version >= 1 && fbDev->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        fbDev->dump(fbDev, buffer, SIZE);
-        result.append(buffer);
-    }
+    mHwc.fbDump(result);
     ConsumerBase::dump(result);
 }
 
index bfa500b..fd7c520 100644 (file)
@@ -30,13 +30,13 @@ namespace android {
 
 class Rect;
 class String8;
+class HWComposer;
 
 // ---------------------------------------------------------------------------
 
 class FramebufferSurface : public ConsumerBase {
 public:
-
-    static sp<FramebufferSurface> create();
+    FramebufferSurface(HWComposer& hwc);
 
     bool isUpdateOnDemand() const { return false; }
     status_t setUpdateRectangle(const Rect& updateRect);
@@ -49,22 +49,12 @@ public:
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
     status_t nextBuffer(sp<GraphicBuffer>* buffer);
 
-    // FIXME: currently there are information we can only get from the
-    // FB HAL, and FB HAL can only be instantiated once on some devices.
-    // Eventually this functionality will have to move in HWC or somewhere else.
-    const framebuffer_device_t* getFbHal() const {
-        return fbDev;
-    }
-
 private:
-    FramebufferSurface();
-    virtual ~FramebufferSurface(); // this class cannot be overloaded
+    virtual ~FramebufferSurface() { }; // this class cannot be overloaded
 
     virtual void onFrameAvailable();
     virtual void freeBufferLocked(int slotIndex);
 
-    framebuffer_device_t* fbDev;
-
     // mCurrentBufferIndex is the slot index of the current buffer or
     // INVALID_BUFFER_SLOT to indicate that either there is no current buffer
     // or the buffer is not associated with a slot.
@@ -73,6 +63,9 @@ private:
     // mCurrentBuffer is the current buffer or NULL to indicate that there is
     // no current buffer.
     sp<GraphicBuffer> mCurrentBuffer;
+
+    // Hardware composer, owned by SurfaceFlinger.
+    HWComposer& mHwc;
 };
 
 // ---------------------------------------------------------------------------
index dca27ba..5c125c8 100644 (file)
@@ -90,10 +90,9 @@ struct HWComposer::cb_context {
 
 HWComposer::HWComposer(
         const sp<SurfaceFlinger>& flinger,
-        EventHandler& handler,
-        framebuffer_device_t const* fbDev)
+        EventHandler& handler)
     : mFlinger(flinger),
-      mModule(0), mHwc(0), mNumDisplays(1),
+      mFbDev(0), mHwc(0), mNumDisplays(1),
       mCBContext(new cb_context),
       mEventHandler(handler),
       mVSyncCount(0), mDebugForceFakeVSync(false)
@@ -107,71 +106,62 @@ HWComposer::HWComposer(
     mDebugForceFakeVSync = atoi(value);
 
     bool needVSyncThread = true;
-    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
-    ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
-    if (err == 0) {
-        err = hwc_open_1(mModule, &mHwc);
-        ALOGE_IF(err, "%s device failed to initialize (%s)",
-                HWC_HARDWARE_COMPOSER, strerror(-err));
-        if (err == 0) {
-            if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
-                    hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
-                    hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
-                ALOGE("%s device version %#x unsupported, will not be used",
-                        HWC_HARDWARE_COMPOSER, mHwc->common.version);
-                hwc_close_1(mHwc);
-                mHwc = NULL;
-            }
-        }
 
-        if (mHwc) {
-            ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
-                    (hwcApiVersion(mHwc) >> 24) & 0xff,
-                    (hwcApiVersion(mHwc) >> 16) & 0xff);
-            if (mHwc->registerProcs) {
-                mCBContext->hwc = this;
-                mCBContext->procs.invalidate = &hook_invalidate;
-                mCBContext->procs.vsync = &hook_vsync;
-                if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-                    mCBContext->procs.hotplug = &hook_hotplug;
-                else
-                    mCBContext->procs.hotplug = NULL;
-                memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
-                mHwc->registerProcs(mHwc, &mCBContext->procs);
-            }
+    // Note: some devices may insist that the FB HAL be opened before HWC.
+    loadFbHalModule();
+    loadHwcModule();
 
-            // always turn vsync off when we start
-            needVSyncThread = false;
-            mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+    if (mHwc) {
+        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
+              (hwcApiVersion(mHwc) >> 24) & 0xff,
+              (hwcApiVersion(mHwc) >> 16) & 0xff);
+        if (mHwc->registerProcs) {
+            mCBContext->hwc = this;
+            mCBContext->procs.invalidate = &hook_invalidate;
+            mCBContext->procs.vsync = &hook_vsync;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+                mCBContext->procs.hotplug = &hook_hotplug;
+            else
+                mCBContext->procs.hotplug = NULL;
+            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
+            mHwc->registerProcs(mHwc, &mCBContext->procs);
+        }
 
-            // these IDs are always reserved
-            for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
-                mAllocatedDisplayIDs.markBit(i);
-            }
+        // don't need a vsync thread if we have a hardware composer
+        needVSyncThread = false;
+        // always turn vsync off when we start
+        mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
 
-            // the number of displays we actually have depends on the
-            // hw composer version
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
-                // 1.2 adds support for virtual displays
-                mNumDisplays = MAX_DISPLAYS;
-            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // 1.1 adds support for multiple displays
-                mNumDisplays = HWC_NUM_DISPLAY_TYPES;
-            } else {
-                mNumDisplays = 1;
-            }
+        // these IDs are always reserved
+        for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
+            mAllocatedDisplayIDs.markBit(i);
+        }
+
+        // the number of displays we actually have depends on the
+        // hw composer version
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+            // 1.2 adds support for virtual displays
+            mNumDisplays = MAX_DISPLAYS;
+        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // 1.1 adds support for multiple displays
+            mNumDisplays = HWC_NUM_DISPLAY_TYPES;
+        } else {
+            mNumDisplays = 1;
         }
     }
 
-    if (fbDev) {
+    if (mFbDev) {
         ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
                 "should only have fbdev if no hwc or hwc is 1.0");
 
         DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
-        disp.xdpi = fbDev->xdpi;
-        disp.ydpi = fbDev->ydpi;
+        disp.xres = mFbDev->width;
+        disp.yres = mFbDev->height;
+        disp.format = mFbDev->format;
+        disp.xdpi = mFbDev->xdpi;
+        disp.ydpi = mFbDev->ydpi;
         if (disp.refresh == 0) {
-            disp.refresh = nsecs_t(1e9 / fbDev->fps);
+            disp.refresh = nsecs_t(1e9 / mFbDev->fps);
             ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh);
         }
         if (disp.refresh == 0) {
@@ -197,9 +187,57 @@ HWComposer::~HWComposer() {
     if (mHwc) {
         hwc_close_1(mHwc);
     }
+    if (mFbDev) {
+        framebuffer_close(mFbDev);
+    }
     delete mCBContext;
 }
 
+// Load and prepare the hardware composer module.  Sets mHwc.
+void HWComposer::loadHwcModule()
+{
+    hw_module_t const* module;
+
+    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
+        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
+        return;
+    }
+
+    int err = hwc_open_1(module, &mHwc);
+    if (err) {
+        ALOGE("%s device failed to initialize (%s)",
+              HWC_HARDWARE_COMPOSER, strerror(-err));
+        return;
+    }
+
+    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
+            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
+            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
+        ALOGE("%s device version %#x unsupported, will not be used",
+              HWC_HARDWARE_COMPOSER, mHwc->common.version);
+        hwc_close_1(mHwc);
+        mHwc = NULL;
+        return;
+    }
+}
+
+// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
+void HWComposer::loadFbHalModule()
+{
+    hw_module_t const* module;
+
+    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) {
+        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
+        return;
+    }
+
+    int err = framebuffer_open(module, &mFbDev);
+    if (err) {
+        ALOGE("framebuffer_open failed (%s)", strerror(-err));
+        return;
+    }
+}
+
 status_t HWComposer::initCheck() const {
     return mHwc ? NO_ERROR : NO_INIT;
 }
@@ -265,6 +303,7 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = {
 void HWComposer::queryDisplayProperties(int disp) {
     ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
 
+    // use zero as default value for unspecified attributes
     int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
     memset(values, 0, sizeof(values));
 
@@ -283,12 +322,10 @@ void HWComposer::queryDisplayProperties(int disp) {
             mDisplayData[disp].refresh = nsecs_t(values[i]);
             break;
         case HWC_DISPLAY_RESOLUTION_X:
-            // TODO: we'll probably want to remember this eventually
-            w = values[i];
+            mDisplayData[disp].xres = values[i];
             break;
         case HWC_DISPLAY_RESOLUTION_Y:
-            // TODO: we'll probably want to remember this eventually
-            h = values[i];
+            mDisplayData[disp].yres = values[i];
             break;
         case HWC_DISPLAY_DPI_X:
             mDisplayData[disp].xdpi = values[i] / 1000.0f;
@@ -336,25 +373,37 @@ status_t HWComposer::freeDisplayId(int32_t id) {
     return NO_ERROR;
 }
 
-nsecs_t HWComposer::getRefreshPeriod() const {
-    return mDisplayData[HWC_DISPLAY_PRIMARY].refresh;
+nsecs_t HWComposer::getRefreshPeriod(int disp) const {
+    return mDisplayData[disp].refresh;
 }
 
-nsecs_t HWComposer::getRefreshTimestamp() const {
+nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
     // the refresh period and whatever closest timestamp we have.
     Mutex::Autolock _l(mLock);
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    return now - ((now - mLastHwVSync) %  mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
+    return now - ((now - mLastHwVSync) %  mDisplayData[disp].refresh);
+}
+
+uint32_t HWComposer::getResolutionX(int disp) const {
+    return mDisplayData[disp].xres;
+}
+
+uint32_t HWComposer::getResolutionY(int disp) const {
+    return mDisplayData[disp].yres;
+}
+
+uint32_t HWComposer::getFormat(int disp) const {
+    return mDisplayData[disp].format;
 }
 
-float HWComposer::getDpiX() const {
-    return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
+float HWComposer::getDpiX(int disp) const {
+    return mDisplayData[disp].xdpi;
 }
 
-float HWComposer::getDpiY() const {
-    return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
+float HWComposer::getDpiY(int disp) const {
+    return mDisplayData[disp].ydpi;
 }
 
 void HWComposer::eventControl(int event, int enabled) {
@@ -493,6 +542,30 @@ size_t HWComposer::getNumLayers(int32_t id) const {
             mDisplayData[id].list->numHwLayers : 0;
 }
 
+int HWComposer::fbPost(buffer_handle_t buffer)
+{
+    return mFbDev->post(mFbDev, buffer);
+}
+
+int HWComposer::fbCompositionComplete()
+{
+    if (mFbDev->compositionComplete) {
+        return mFbDev->compositionComplete(mFbDev);
+    } else {
+        return INVALID_OPERATION;
+    }
+}
+
+void HWComposer::fbDump(String8& result) {
+    if (mFbDev->common.version >= 1 && mFbDev->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
+        mFbDev->dump(mFbDev, buffer, SIZE);
+        result.append(buffer);
+    }
+}
+
+
 /*
  * Helper template to implement a concrete HWCLayer
  * This holds the pointer to the concrete hwc layer type
@@ -680,7 +753,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
 HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
     : mHwc(hwc), mEnabled(false),
       mNextFakeVSync(0),
-      mRefreshPeriod(hwc.getRefreshPeriod())
+      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
 {
 }
 
index a49a023..4c520b1 100644 (file)
@@ -64,8 +64,7 @@ public:
 
     HWComposer(
             const sp<SurfaceFlinger>& flinger,
-            EventHandler& handler,
-            framebuffer_device_t const* fbDev);
+            EventHandler& handler);
 
     ~HWComposer();
 
@@ -107,6 +106,11 @@ public:
     // needed forward declarations
     class LayerListIterator;
 
+    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
+    int fbPost(buffer_handle_t buffer);
+    int fbCompositionComplete();
+    void fbDump(String8& result);
+
     /*
      * Interface to hardware composer's layers functionality.
      * This abstracts the HAL interface to layers which can evolve in
@@ -208,10 +212,15 @@ public:
 
     void eventControl(int event, int enabled);
 
-    nsecs_t getRefreshPeriod() const;
-    nsecs_t getRefreshTimestamp() const;
-    float getDpiX() const;
-    float getDpiY() const;
+    // Query display parameters.  Pass in a display index (e.g.
+    // HWC_DISPLAY_PRIMARY).
+    nsecs_t getRefreshPeriod(int disp) const;
+    nsecs_t getRefreshTimestamp(int disp) const;
+    uint32_t getResolutionX(int disp) const;
+    uint32_t getResolutionY(int disp) const;
+    uint32_t getFormat(int disp) const;
+    float getDpiX(int disp) const;
+    float getDpiY(int disp) const;
 
     // this class is only used to fake the VSync event on systems that don't
     // have it.
@@ -236,6 +245,8 @@ public:
             const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
 
 private:
+    void loadHwcModule();
+    void loadFbHalModule();
 
     LayerListIterator getLayerIterator(int32_t id, size_t index);
     size_t getNumLayers(int32_t id) const;
@@ -261,6 +272,9 @@ private:
         ~DisplayData() {
             free(list);
         }
+        uint32_t xres;
+        uint32_t yres;
+        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
         float xdpi;
         float ydpi;
         nsecs_t refresh;
@@ -271,7 +285,7 @@ private:
     };
 
     sp<SurfaceFlinger>              mFlinger;
-    hw_module_t const*              mModule;
+    framebuffer_device_t*           mFbDev;
     struct hwc_composer_device_1*   mHwc;
     // invariant: mLists[0] != NULL iff mHwc != NULL
     // mLists[i>0] can be NULL. that display is to be ignored
index e78059d..75eff9f 100644 (file)
@@ -515,7 +515,7 @@ void Layer::onPostComposition() {
         const size_t offset = mFrameLatencyOffset;
         mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp();
         mFrameStats[offset].set = systemTime();
-        mFrameStats[offset].vsync = hwc.getRefreshTimestamp();
+        mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
         mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128;
         mFrameLatencyNeeded = false;
     }
@@ -726,7 +726,8 @@ void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const
 {
     LayerBaseClient::dumpStats(result, buffer, SIZE);
     const size_t o = mFrameLatencyOffset;
-    const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod();
+    const nsecs_t period =
+            mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
     result.appendFormat("%lld\n", period);
     for (size_t i=0 ; i<128 ; i++) {
         const size_t index = (o+i) % 128;
index ef910d9..cb2c8c0 100644 (file)
@@ -366,13 +366,18 @@ status_t SurfaceFlinger::readyToRun()
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
-    // initialize EGL
+    // initialize EGL for the default display
     mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglInitialize(mEGLDisplay, NULL, NULL);
 
+    // Initialize the H/W composer object.  There may or may not be an
+    // actual hardware composer underneath.
+    mHwc = new HWComposer(this,
+            *static_cast<HWComposer::EventHandler *>(this));
+
     // Initialize the main display
     // create native window to main display
-    sp<FramebufferSurface> fbs = FramebufferSurface::create();
+    sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc);
     if (fbs == NULL) {
         ALOGE("Display subsystem failed to initialize. check logs. exiting...");
         exit(0);
@@ -408,11 +413,6 @@ status_t SurfaceFlinger::readyToRun()
     mEventThread = new EventThread(this);
     mEventQueue.setEventThread(mEventThread);
 
-    // initialize the H/W composer
-    mHwc = new HWComposer(this,
-            *static_cast<HWComposer::EventHandler *>(this),
-            fbs->getFbHal());
-
     // initialize our drawing state
     mDrawingState = mCurrentState;
 
@@ -500,8 +500,8 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo*
     }
 
     const HWComposer& hwc(getHwComposer());
-    float xdpi = hwc.getDpiX();
-    float ydpi = hwc.getDpiY();
+    float xdpi = hwc.getDpiX(HWC_DISPLAY_PRIMARY);
+    float ydpi = hwc.getDpiY(HWC_DISPLAY_PRIMARY);
 
     // TODO: Not sure if display density should handled by SF any longer
     class Density {
@@ -538,7 +538,7 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo*
     info->h = hw->getHeight();
     info->xdpi = xdpi;
     info->ydpi = ydpi;
-    info->fps = float(1e9 / hwc.getRefreshPeriod());
+    info->fps = float(1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY));
     info->density = density;
     info->orientation = hw->getOrientation();
     // TODO: this needs to go away (currently needed only by webkit)
@@ -2018,9 +2018,9 @@ void SurfaceFlinger::dumpAllLocked(
             mLastSwapBufferTime/1000.0,
             mLastTransactionTime/1000.0,
             mTransactionFlags,
-            1e9 / hwc.getRefreshPeriod(),
-            hwc.getDpiX(),
-            hwc.getDpiY());
+            1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
+            hwc.getDpiX(HWC_DISPLAY_PRIMARY),
+            hwc.getDpiY(HWC_DISPLAY_PRIMARY));
     result.append(buffer);
 
     snprintf(buffer, SIZE, "  eglSwapBuffers time: %f us\n",