add support hwc 1.1

Bug: 7124069

Change-Id: I53d705105c4ad8954d3f50ee4f4c8b7ec936b871
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 92a3fcc..a4f8fb6 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -74,15 +74,13 @@
     mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS);
 }
 
-status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
+status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
     Mutex::Autolock lock(mMutex);
 
     BufferQueue::BufferItem item;
     status_t err = acquireBufferLocked(&item);
     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-        if (buffer != NULL) {
-            *buffer = mCurrentBuffer;
-        }
+        outBuffer = mCurrentBuffer;
         return NO_ERROR;
     } else if (err != NO_ERROR) {
         ALOGE("error acquiring buffer: %s (%d)", strerror(-err), err);
@@ -107,32 +105,24 @@
             return err;
         }
     }
-
     mCurrentBufferSlot = item.mBuf;
     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
-    if (item.mFence != NULL) {
-        item.mFence->wait(Fence::TIMEOUT_NEVER);
-    }
-
-    if (buffer != NULL) {
-        *buffer = mCurrentBuffer;
-    }
-
+    outFence = item.mFence;
+    outBuffer = mCurrentBuffer;
     return NO_ERROR;
 }
 
 // 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.
     sp<GraphicBuffer> buf;
-    status_t err = nextBuffer(&buf);
+    sp<Fence> acquireFence;
+    status_t err = nextBuffer(buf, acquireFence);
     if (err != NO_ERROR) {
-        ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
+        ALOGE("error latching nnext FramebufferSurface buffer: %s (%d)",
                 strerror(-err), err);
         return;
     }
-    err = mHwc.fbPost(buf->handle);
+    err = mHwc.fbPost(0, acquireFence, buf); // FIXME: use real display id
     if (err != NO_ERROR) {
         ALOGE("error posting framebuffer: %d", err);
     }
@@ -145,6 +135,19 @@
     }
 }
 
+status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
+    status_t err = NO_ERROR;
+    if (fenceFd >= 0) {
+        sp<Fence> fence(new Fence(fenceFd));
+        if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
+            status_t err = addReleaseFence(mCurrentBufferSlot, fence);
+            ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
+                    strerror(-err), err);
+        }
+    }
+    return err;
+}
+
 status_t FramebufferSurface::setUpdateRectangle(const Rect& r)
 {
     return INVALID_OPERATION;
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index fd7c520..717a3f1 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -44,10 +44,13 @@
 
     virtual void dump(String8& result);
 
-    // nextBuffer waits for and then latches the next buffer from the
-    // BufferQueue and releases the previously latched buffer to the
-    // BufferQueue.  The new buffer is returned in the 'buffer' argument.
-    status_t nextBuffer(sp<GraphicBuffer>* buffer);
+    // setReleaseFenceFd stores a fence file descriptor that will signal when the
+    // current buffer is no longer being read. This fence will be returned to
+    // the producer when the current buffer is released by updateTexImage().
+    // Multiple fences can be set for a given buffer; they will be merged into
+    // a single union fence. The SurfaceTexture will close the file descriptor
+    // when finished with it.
+    status_t setReleaseFenceFd(int fenceFd);
 
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
@@ -55,6 +58,11 @@
     virtual void onFrameAvailable();
     virtual void freeBufferLocked(int slotIndex);
 
+    // nextBuffer waits for and then latches the next buffer from the
+    // BufferQueue and releases the previously latched buffer to the
+    // BufferQueue.  The new buffer is returned in the 'buffer' argument.
+    status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
+
     // 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.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 81640af..9c04fc0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 
 #include <utils/Errors.h>
+#include <utils/misc.h>
 #include <utils/String8.h>
 #include <utils/Thread.h>
 #include <utils/Trace.h>
@@ -43,6 +44,7 @@
 #include "LayerBase.h"
 #include "HWComposer.h"
 #include "SurfaceFlinger.h"
+#include <utils/CallStack.h>
 
 namespace android {
 
@@ -111,6 +113,14 @@
     loadFbHalModule();
     loadHwcModule();
 
+    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        // close FB HAL if we don't needed it.
+        // FIXME: this is temporary until we're not forced to open FB HAL
+        // before HWC.
+        framebuffer_close(mFbDev);
+        mFbDev = NULL;
+    }
+
     // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
     if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
             && !mFbDev) {
@@ -310,7 +320,7 @@
 #define ANDROID_DENSITY_XHIGH 320
 
 void HWComposer::queryDisplayProperties(int disp) {
-    ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
 
     // use zero as default value for unspecified attributes
     int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
@@ -319,7 +329,11 @@
     uint32_t config;
     size_t numConfigs = 1;
     status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs);
+    LOG_ALWAYS_FATAL_IF(err, "getDisplayAttributes failed (%s)", strerror(-err));
+
     if (err == NO_ERROR) {
+        ALOGD("config=%d, numConfigs=%d, NUM_DISPLAY_ATTRIBUTES=%d",
+                config, numConfigs, NUM_DISPLAY_ATTRIBUTES);
         mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES,
                 values);
     }
@@ -343,8 +357,8 @@
             mDisplayData[disp].ydpi = values[i] / 1000.0f;
             break;
         default:
-            ALOG_ASSERT(false, "unknown display attribute %#x",
-                    DISPLAY_ATTRIBUTES[i]);
+            ALOG_ASSERT(false, "unknown display attribute[%d] %#x",
+                    i, DISPLAY_ATTRIBUTES[i]);
             break;
         }
     }
@@ -439,13 +453,35 @@
 
     if (mHwc) {
         DisplayData& disp(mDisplayData[id]);
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // we need space for the HWC_FRAMEBUFFER_TARGET
+            numLayers++;
+        }
         if (disp.capacity < numLayers || disp.list == NULL) {
-            const size_t size = sizeof(hwc_display_contents_1_t)
+            size_t size = sizeof(hwc_display_contents_1_t)
                     + numLayers * sizeof(hwc_layer_1_t);
             free(disp.list);
             disp.list = (hwc_display_contents_1_t*)malloc(size);
             disp.capacity = numLayers;
         }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
+            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
+            const hwc_rect_t r = { 0, 0, disp.width, disp.height };
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+            disp.framebufferTarget->hints = 0;
+            disp.framebufferTarget->flags = 0;
+            disp.framebufferTarget->handle = disp.fbTargetHandle;
+            disp.framebufferTarget->transform = 0;
+            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
+            disp.framebufferTarget->sourceCrop = r;
+            disp.framebufferTarget->displayFrame = r;
+            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
+            disp.framebufferTarget->visibleRegionScreen.rects =
+                &disp.framebufferTarget->displayFrame;
+            disp.framebufferTarget->acquireFenceFd = -1;
+            disp.framebufferTarget->releaseFenceFd = -1;
+        }
         disp.list->retireFenceFd = -1;
         disp.list->flags = HWC_GEOMETRY_CHANGED;
         disp.list->numHwLayers = numLayers;
@@ -453,9 +489,46 @@
     return NO_ERROR;
 }
 
+status_t HWComposer::setFramebufferTarget(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    DisplayData& disp(mDisplayData[id]);
+    if (!disp.framebufferTarget) {
+        // this should never happen, but apparently eglCreateWindowSurface()
+        // triggers a SurfaceTextureClient::queueBuffer()  on some
+        // devices (!?) -- log and ignore.
+        ALOGE("HWComposer: framebufferTarget is null");
+        CallStack stack;
+        stack.update();
+        stack.dump("");
+        return NO_ERROR;
+    }
+
+    int acquireFenceFd = -1;
+    if (acquireFence != NULL) {
+        acquireFenceFd = acquireFence->dup();
+    }
+
+    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
+    disp.fbTargetHandle = buf->handle;
+    disp.framebufferTarget->handle = disp.fbTargetHandle;
+    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
+    return NO_ERROR;
+}
+
 status_t HWComposer::prepare() {
     for (size_t i=0 ; i<mNumDisplays ; i++) {
-        mLists[i] = mDisplayData[i].list;
+        DisplayData& disp(mDisplayData[i]);
+        if (disp.framebufferTarget) {
+            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
+            // DO NOT reset the handle field to NULL, because it's possible
+            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
+            // in which case, we should continue to use the same buffer.
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+        }
+        mLists[i] = disp.list;
         if (mLists[i]) {
             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
                 mLists[i]->outbuf = NULL;
@@ -472,6 +545,8 @@
     }
 
     int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
+    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
+
     if (err == NO_ERROR) {
         // here we're just making sure that "skip" layers are set
         // to HWC_FRAMEBUFFER and we're also counting how many layers
@@ -483,6 +558,10 @@
             if (disp.list) {
                 for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
                     hwc_layer_1_t& l = disp.list->hwLayers[i];
+
+                    //ALOGD("prepare: %d, type=%d, handle=%p",
+                    //        i, l.compositionType, l.handle);
+
                     if (l.flags & HWC_SKIP_LAYER) {
                         l.compositionType = HWC_FRAMEBUFFER;
                     }
@@ -511,6 +590,21 @@
     return mDisplayData[id].hasFbComp;
 }
 
+int HWComposer::getAndResetReleaseFenceFd(int32_t id) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return BAD_INDEX;
+
+    int fd = INVALID_OPERATION;
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (disp.framebufferTarget) {
+            fd = disp.framebufferTarget->releaseFenceFd;
+            disp.framebufferTarget->releaseFenceFd = -1;
+        }
+    }
+    return fd;
+}
+
 status_t HWComposer::commit() {
     int err = NO_ERROR;
     if (mHwc) {
@@ -553,38 +647,43 @@
     return NO_ERROR;
 }
 
-size_t HWComposer::getNumLayers(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return 0;
-    }
-    return (mHwc && mDisplayData[id].list) ?
-            mDisplayData[id].list->numHwLayers : 0;
-}
-
 int HWComposer::getVisualID() const {
     if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
+        // is supported by the implementation. we can only be in this case
+        // if we have HWC 1.1
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     } else {
         return mFbDev->format;
     }
 }
 
-int HWComposer::fbPost(buffer_handle_t buffer) {
-    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
-        return mFbDev->post(mFbDev, buffer);
+bool HWComposer::supportsFramebufferTarget() const {
+    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+}
+
+int HWComposer::fbPost(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        return setFramebufferTarget(id, acquireFence, buffer);
+    } else {
+        if (acquireFence != NULL) {
+            acquireFence->wait(Fence::TIMEOUT_NEVER);
+        }
+        return mFbDev->post(mFbDev, buffer->handle);
     }
-    return NO_ERROR;
 }
 
 int HWComposer::fbCompositionComplete() {
-    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
-        if (mFbDev->compositionComplete) {
-            return mFbDev->compositionComplete(mFbDev);
-        } else {
-            return INVALID_OPERATION;
-        }
+    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+        return NO_ERROR;
+
+    if (mFbDev->compositionComplete) {
+        return mFbDev->compositionComplete(mFbDev);
+    } else {
+        return INVALID_OPERATION;
     }
-    return NO_ERROR;
 }
 
 void HWComposer::fbDump(String8& result) {
@@ -596,7 +695,6 @@
     }
 }
 
-
 /*
  * Helper template to implement a concrete HWCLayer
  * This holds the pointer to the concrete hwc layer type
@@ -733,7 +831,22 @@
  * returns an iterator on the end of the layer list
  */
 HWComposer::LayerListIterator HWComposer::end(int32_t id) {
-    return getLayerIterator(id, getNumLayers(id));
+    size_t numLayers = 0;
+    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (mHwc && disp.list) {
+            numLayers = disp.list->numHwLayers;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
+                // which we ignore when iterating through the layer list.
+                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
+                if (numLayers) {
+                    numLayers--;
+                }
+            }
+        }
+    }
+    return getLayerIterator(id, numLayers);
 }
 
 void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
@@ -747,27 +860,47 @@
                 result.appendFormat("  id=%d, numHwLayers=%u, flags=%08x\n",
                         i, disp.list->numHwLayers, disp.list->flags);
                 result.append(
-                        "   type   |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
-                        "----------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
-                //      " ________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
+                        "    type    |  handle  |   hints  |   flags  | tr | blend |  format  |       source crop         |           frame           name \n"
+                        "------------+----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n");
+                //      " __________ | ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____]
                 for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
                     const hwc_layer_1_t&l = disp.list->hwLayers[i];
-                    const sp<LayerBase> layer(visibleLayersSortedByZ[i]);
                     int32_t format = -1;
-                    if (layer->getLayer() != NULL) {
-                        const sp<GraphicBuffer>& buffer(
+                    String8 name("unknown");
+                    if (i < visibleLayersSortedByZ.size()) {
+                        const sp<LayerBase>& layer(visibleLayersSortedByZ[i]);
+                        if (layer->getLayer() != NULL) {
+                            const sp<GraphicBuffer>& buffer(
                                 layer->getLayer()->getActiveBuffer());
-                        if (buffer != NULL) {
-                            format = buffer->getPixelFormat();
+                            if (buffer != NULL) {
+                                format = buffer->getPixelFormat();
+                            }
                         }
+                        name = layer->getName();
                     }
+
+                    int type = l.compositionType;
+                    if (type == HWC_FRAMEBUFFER_TARGET) {
+                        name = "HWC_FRAMEBUFFER_TARGET";
+                        format = disp.format;
+                    }
+
+                    static char const* compositionTypeName[] = {
+                            "GLES",
+                            "HWC",
+                            "BACKGROUND",
+                            "FB TARGET",
+                            "UNKNOWN"};
+                    if (type >= NELEM(compositionTypeName))
+                        type = NELEM(compositionTypeName) - 1;
+
                     result.appendFormat(
-                            " %8s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
-                            l.compositionType ? "OVERLAY" : "FB",
+                            " %10s | %08x | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
+                                    compositionTypeName[type],
                                     intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, format,
                                     l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
                                     l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                    layer->getName().string());
+                                    name.string());
                 }
             }
         }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index fe928c5..f253ecc 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -36,6 +36,7 @@
 
 struct hwc_composer_device_1;
 struct hwc_display_contents_1;
+struct hwc_layer_1;
 struct hwc_procs;
 struct framebuffer_device_t;
 
@@ -43,6 +44,7 @@
 // ---------------------------------------------------------------------------
 
 class GraphicBuffer;
+class Fence;
 class LayerBase;
 class Region;
 class String8;
@@ -97,12 +99,18 @@
     // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
     status_t createWorkList(int32_t id, size_t numLayers);
 
+    bool supportsFramebufferTarget() const;
+
     // does this display have layers handled by HWC
     bool hasHwcComposition(int32_t id) const;
 
     // does this display have layers handled by GLES
     bool hasGlesComposition(int32_t id) const;
 
+    // get the releaseFence file descriptor for the given display
+    // the release fence is only valid after commit()
+    int getAndResetReleaseFenceFd(int32_t id);
+
     // needed forward declarations
     class LayerListIterator;
 
@@ -111,7 +119,7 @@
     int getVisualID() const;
 
     // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
-    int fbPost(buffer_handle_t buffer);
+    int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
     int fbCompositionComplete();
     void fbDump(String8& result);
 
@@ -253,7 +261,6 @@
     void loadFbHalModule();
 
     LayerListIterator getLayerIterator(int32_t id, size_t index);
-    size_t getNumLayers(int32_t id) const;
 
     struct cb_context;
 
@@ -269,10 +276,15 @@
 
     void queryDisplayProperties(int disp);
 
+    status_t setFramebufferTarget(int32_t id,
+            const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+
+
     struct DisplayData {
         DisplayData() : xdpi(0), ydpi(0), refresh(0),
             hasFbComp(false), hasOvComp(false),
-            capacity(0), list(NULL) { }
+            capacity(0), list(NULL),
+            framebufferTarget(NULL), fbTargetHandle(NULL) { }
         ~DisplayData() {
             free(list);
         }
@@ -286,6 +298,8 @@
         bool hasOvComp;
         size_t capacity;
         hwc_display_contents_1* list;
+        hwc_layer_1* framebufferTarget;
+        buffer_handle_t fbTargetHandle;
     };
 
     sp<SurfaceFlinger>              mFlinger;