Merge "BufferQueue: clean up buffer counting" into jb-mr1-dev
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 73214a4..a143d81 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -148,11 +148,6 @@
 public:
     ScreenshotClient();
 
-    // TODO: Remove me.  Do not use.
-    // This is a compatibility shim for one product whose drivers are depending on
-    // this legacy function (when they shouldn't).
-    status_t update();
-
     // frees the previous screenshot and capture a new one
     status_t update(const sp<IBinder>& display);
     status_t update(const sp<IBinder>& display,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0ffa932..e4922a4 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -558,14 +558,6 @@
     : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) {
 }
 
-// TODO: Remove me.  Do not use.
-// This is a compatibility shim for one product whose drivers are depending on
-// this legacy function (when they shouldn't).
-status_t ScreenshotClient::update() {
-    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
-    return update(sm->getBuiltInDisplay(0));
-}
-
 status_t ScreenshotClient::update(const sp<IBinder>& display) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1678fe1..75c228d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -46,8 +46,31 @@
 
 namespace android {
 
-static bool hwcHasVersion(const hwc_composer_device_1_t* hwc, uint32_t version) {
-    return hwc->common.version >= version;
+#define MIN_HWC_HEADER_VERSION 0
+
+static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    if (MIN_HWC_HEADER_VERSION == 0 &&
+            (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+        // legacy version encoding
+        hwcVersion <<= 16;
+    }
+    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+}
+
+static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    if (MIN_HWC_HEADER_VERSION == 0 &&
+            (hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK) == 0) {
+        // legacy version encoding
+        hwcVersion <<= 16;
+    }
+    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
+}
+
+static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
+        uint32_t version) {
+    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
 }
 
 // ---------------------------------------------------------------------------
@@ -91,8 +114,10 @@
         ALOGE_IF(err, "%s device failed to initialize (%s)",
                 HWC_HARDWARE_COMPOSER, strerror(-err));
         if (err == 0) {
-            if (mHwc->common.version < HWC_DEVICE_API_VERSION_1_0) {
-                ALOGE("%s device version %#x too old, will not be used",
+            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;
@@ -100,6 +125,9 @@
         }
 
         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;
@@ -125,12 +153,14 @@
 
             // the number of displays we actually have depends on the
             // hw composer version
-            if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_1) {
-                // 1.1 adds support for multiple displays
-                mNumDisplays = HWC_NUM_DISPLAY_TYPES;
-            } else if (mHwc->common.version > HWC_DEVICE_API_VERSION_1_1) {
+            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;
             }
         }
     }
@@ -326,7 +356,7 @@
 status_t HWComposer::commit() {
     int err = NO_ERROR;
     if (mHwc) {
-        if (mHwc->common.version == HWC_DEVICE_API_VERSION_1_0) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
             // On version 1.0, the OpenGL ES target surface is communicated
             // by the (dpy, sur) fields and we are guaranteed to have only
             // a single display.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1162432..cd1b336 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -944,7 +944,7 @@
         if (!curr.isIdenticalTo(draw)) {
             mVisibleRegionsDirty = true;
             const size_t cc = curr.size();
-            const size_t dc = draw.size();
+                  size_t dc = draw.size();
 
             // find the displays that were removed
             // (ie: in drawing state but not in current state)
@@ -965,27 +965,27 @@
                     const wp<IBinder>& display(curr.keyAt(j));
                     if (state.surface->asBinder() != draw[i].surface->asBinder()) {
                         // changing the surface is like destroying and
-                        // recreating the DisplayDevice
-                        sp<SurfaceTextureClient> stc(
-                                new SurfaceTextureClient(state.surface));
-                        sp<DisplayDevice> disp = new DisplayDevice(this,
-                            state.type, display, stc, NULL, mEGLConfig);
+                        // recreating the DisplayDevice, so we just remove it
+                        // from the drawing state, so that it get re-added
+                        // below.
+                        mDisplays.removeItem(display);
+                        mDrawingState.displays.removeItemsAt(i);
+                        dc--; i--;
+                        // at this point we must loop to the next item
+                        continue;
+                    }
 
-                        disp->setLayerStack(state.layerStack);
-                        disp->setOrientation(state.orientation);
-                        // TODO: take viewport and frame into account
-                        mDisplays.replaceValueFor(display, disp);
-                    }
-                    if (state.layerStack != draw[i].layerStack) {
-                        const sp<DisplayDevice>& disp(getDisplayDevice(display));
-                        disp->setLayerStack(state.layerStack);
-                    }
-                    if (state.orientation != draw[i].orientation ||
-                        state.viewport != draw[i].viewport ||
-                        state.frame != draw[i].frame) {
-                        const sp<DisplayDevice>& disp(getDisplayDevice(display));
-                        disp->setOrientation(state.orientation);
-                        // TODO: take viewport and frame into account
+                    const sp<DisplayDevice>& disp(getDisplayDevice(display));
+                    if (disp != NULL) {
+                        if (state.layerStack != draw[i].layerStack) {
+                            disp->setLayerStack(state.layerStack);
+                        }
+                        if (state.orientation != draw[i].orientation ||
+                                state.viewport != draw[i].viewport ||
+                                state.frame != draw[i].frame) {
+                            disp->setOrientation(state.orientation);
+                            // TODO: take viewport and frame into account
+                        }
                     }
                 }
             }
@@ -995,12 +995,17 @@
             for (size_t i=0 ; i<cc ; i++) {
                 if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                     const DisplayDeviceState& state(curr[i]);
-                    sp<SurfaceTextureClient> stc(
-                            new SurfaceTextureClient(state.surface));
-                    const wp<IBinder>& display(curr.keyAt(i));
-                    sp<DisplayDevice> disp = new DisplayDevice(this,
-                        state.type, display, stc, 0, mEGLConfig);
-                    mDisplays.add(display, disp);
+                    if (state.surface != NULL) {
+                        sp<SurfaceTextureClient> stc(
+                                new SurfaceTextureClient(state.surface));
+                        const wp<IBinder>& display(curr.keyAt(i));
+                        sp<DisplayDevice> disp = new DisplayDevice(this,
+                                state.type, display, stc, 0, mEGLConfig);
+                        disp->setLayerStack(state.layerStack);
+                        disp->setOrientation(state.orientation);
+                        // TODO: take viewport and frame into account
+                        mDisplays.add(display, disp);
+                    }
                 }
             }
         }
@@ -1264,15 +1269,13 @@
 
 void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
 {
+    const int32_t id = hw->getHwcDisplayId();
     HWComposer& hwc(getHwComposer());
-    int32_t id = hw->getHwcDisplayId();
     HWComposer::LayerListIterator cur = hwc.begin(id);
     const HWComposer::LayerListIterator end = hwc.end(id);
 
-    const bool hasGlesComposition = hwc.hasGlesComposition(id);
-    const bool hasHwcComposition = hwc.hasHwcComposition(id);
-    if (cur==end || hasGlesComposition) {
-
+    const bool hasGlesComposition = hwc.hasGlesComposition(id) || (cur==end);
+    if (hasGlesComposition) {
         DisplayDevice::makeCurrent(hw, mEGLContext);
 
         // set the frame buffer
@@ -1280,6 +1283,7 @@
         glLoadIdentity();
 
         // Never touch the framebuffer if we don't have any framebuffer layers
+        const bool hasHwcComposition = hwc.hasHwcComposition(id);
         if (hasHwcComposition) {
             // when using overlays, we assume a fully transparent framebuffer
             // NOTE: we could reduce how much we need to clear, for instance
@@ -1296,38 +1300,49 @@
                 drawWormhole(hw, region);
             }
         }
+    }
 
-        /*
-         * and then, render the layers targeted at the framebuffer
-         */
+    /*
+     * and then, render the layers targeted at the framebuffer
+     */
 
-        const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
-        const size_t count = layers.size();
-        const Transform& tr = hw->getTransform();
-        for (size_t i=0 ; i<count ; ++i) {
+    const Vector< sp<LayerBase> >& layers(hw->getVisibleLayersSortedByZ());
+    const size_t count = layers.size();
+    const Transform& tr = hw->getTransform();
+    if (cur != end) {
+        // we're using h/w composer
+        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
             const sp<LayerBase>& layer(layers[i]);
             const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
-            if (cur != end) {
-                // we're using h/w composer
-                if (!clip.isEmpty()) {
-                    if (cur->getCompositionType() == HWC_OVERLAY) {
-                        if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
-                                && layer->isOpaque()) {
+            if (!clip.isEmpty()) {
+                switch (cur->getCompositionType()) {
+                    case HWC_OVERLAY: {
+                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
+                                && i
+                                && layer->isOpaque()
+                                && hasGlesComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
                             layer->clearWithOpenGL(hw, clip);
                         }
-                    } else {
-                        layer->draw(hw, clip);
+                        break;
                     }
-                    layer->setAcquireFence(hw, *cur);
+                    case HWC_FRAMEBUFFER: {
+                        layer->draw(hw, clip);
+                        break;
+                    }
                 }
-                ++cur;
-            } else {
-                // we're not using h/w composer
-                if (!clip.isEmpty()) {
-                    layer->draw(hw, clip);
-                }
+            }
+            layer->setAcquireFence(hw, *cur);
+        }
+    } else {
+        // we're not using h/w composer
+        for (size_t i=0 ; i<count ; ++i) {
+            const sp<LayerBase>& layer(layers[i]);
+            const Region clip(dirty.intersect(
+                    tr.transform(layer->visibleRegion)));
+            if (!clip.isEmpty()) {
+                layer->draw(hw, clip);
             }
         }
     }