OSDN Git Service

HWC2: Don't set null handle for client layers
[android-x86/frameworks-native.git] / services / surfaceflinger / Layer.cpp
index ed320cb..928a6ba 100644 (file)
@@ -1,4 +1,8 @@
 /*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ *
  * Copyright (C) 2007 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -95,7 +99,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
         mQueueItems(),
         mLastFrameNumberReceived(0),
         mUpdateTexImageFailed(false),
-        mAutoRefresh(false)
+        mAutoRefresh(false),
+        mFreezePositionUpdates(false),
+        mTransformHint(0)
 {
 #ifdef USE_HWC2
     ALOGV("Creating Layer %s", name.string());
@@ -129,10 +135,12 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
 #else
     mCurrentState.alpha = 0xFF;
 #endif
+    mCurrentState.blur = 0xFF;
     mCurrentState.layerStack = 0;
     mCurrentState.flags = layerFlags;
     mCurrentState.sequence = 0;
     mCurrentState.requested = mCurrentState.active;
+    mCurrentState.color = 0;
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
@@ -362,7 +370,7 @@ Rect Layer::getContentCrop() const {
     return crop;
 }
 
-static Rect reduce(const Rect& win, const Region& exclude) {
+Rect Layer::reduce(const Rect& win, const Region& exclude) const{
     if (CC_LIKELY(exclude.isEmpty())) {
         return win;
     }
@@ -448,17 +456,10 @@ FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
         if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
             invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                     NATIVE_WINDOW_TRANSFORM_FLIP_H;
-            // If the transform has been rotated the axis of flip has been swapped
-            // so we need to swap which flip operations we are performing
-            bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
-            bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
-            if (is_h_flipped != is_v_flipped) {
-                invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
-            }
         }
         // and apply to the current transform
-        invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
+        invTransform = (Transform(invTransformOrient) * Transform(invTransform))
+                .getOrientation();
     }
 
     int winWidth = s.active.w;
@@ -542,7 +543,11 @@ void Layer::setGeometry(
                 to_string(error).c_str(), static_cast<int32_t>(error));
     }
 #else
+#if defined(QTI_BSP) && !defined(QCOM_BSP_LEGACY)
+    if (!isOpaque(s)) {
+#else
     if (!isOpaque(s) || s.alpha != 0xFF) {
+#endif
         layer.setBlending(mPremultipliedAlpha ?
                 HWC_BLENDING_PREMULT :
                 HWC_BLENDING_COVERAGE);
@@ -623,6 +628,7 @@ void Layer::setGeometry(
     }
     const Transform& tr(hw->getTransform());
     layer.setFrame(tr.transform(frame));
+    setPosition(hw, layer, s);
     layer.setCrop(computeCrop(hw));
     layer.setPlaneAlpha(s.alpha);
 #endif
@@ -645,23 +651,13 @@ void Layer::setGeometry(
          */
         uint32_t invTransform =
                 DisplayDevice::getPrimaryDisplayOrientationTransform();
-
-        uint32_t t_orientation = transform.getOrientation();
         // calculate the inverse transform
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
             invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                     NATIVE_WINDOW_TRANSFORM_FLIP_H;
-            // If the transform has been rotated the axis of flip has been swapped
-            // so we need to swap which flip operations we are performing
-            bool is_h_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
-            bool is_v_flipped = (t_orientation & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
-            if (is_h_flipped != is_v_flipped) {
-                t_orientation ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
-            }
         }
         // and apply to the current transform
-        transform = Transform(t_orientation) * Transform(invTransform);
+        transform = Transform(invTransform) * transform;
     }
 
     // this gives us only the "orientation" component of the transform
@@ -721,53 +717,45 @@ void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
         surfaceDamageRegion.dump(LOG_TAG);
     }
 
-    auto compositionType = HWC2::Composition::Invalid;
+    // Sideband layers
     if (mSidebandStream.get()) {
-        compositionType = HWC2::Composition::Sideband;
-        auto error = hwcLayer->setSidebandStream(mSidebandStream->handle());
+        setCompositionType(hwcId, HWC2::Composition::Sideband);
+        ALOGV("[%s] Requesting Sideband composition", mName.string());
+        error = hwcLayer->setSidebandStream(mSidebandStream->handle());
         if (error != HWC2::Error::None) {
             ALOGE("[%s] Failed to set sideband stream %p: %s (%d)",
                     mName.string(), mSidebandStream->handle(),
                     to_string(error).c_str(), static_cast<int32_t>(error));
-            return;
-        }
-    } else {
-        if (mActiveBuffer == nullptr || mActiveBuffer->handle == nullptr) {
-            compositionType = HWC2::Composition::Client;
-            auto error = hwcLayer->setBuffer(nullptr, Fence::NO_FENCE);
-            if (error != HWC2::Error::None) {
-                ALOGE("[%s] Failed to set null buffer: %s (%d)", mName.string(),
-                        to_string(error).c_str(), static_cast<int32_t>(error));
-                return;
-            }
-        } else {
-            if (mPotentialCursor) {
-                compositionType = HWC2::Composition::Cursor;
-            }
-            auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-            auto error = hwcLayer->setBuffer(mActiveBuffer->handle,
-                    acquireFence);
-            if (error != HWC2::Error::None) {
-                ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
-                        mActiveBuffer->handle, to_string(error).c_str(),
-                        static_cast<int32_t>(error));
-                return;
-            }
-            // If it's not a cursor, default to device composition
         }
+        return;
     }
 
-    if (mHwcLayers[hwcId].forceClientComposition) {
-        ALOGV("[%s] Forcing Client composition", mName.string());
+    // Client or SolidColor layers
+    if (mActiveBuffer == nullptr || mActiveBuffer->handle == nullptr ||
+            mHwcLayers[hwcId].forceClientComposition) {
+        // TODO: This also includes solid color layers, but no API exists to
+        // setup a solid color layer yet
+        ALOGV("[%s] Requesting Client composition", mName.string());
         setCompositionType(hwcId, HWC2::Composition::Client);
-    } else if (compositionType != HWC2::Composition::Invalid) {
-        ALOGV("[%s] Requesting %s composition", mName.string(),
-                to_string(compositionType).c_str());
-        setCompositionType(hwcId, compositionType);
+        return;
+    }
+
+    // Device or Cursor layers
+    if (mPotentialCursor) {
+        ALOGV("[%s] Requesting Cursor composition", mName.string());
+        setCompositionType(hwcId, HWC2::Composition::Cursor);
     } else {
         ALOGV("[%s] Requesting Device composition", mName.string());
         setCompositionType(hwcId, HWC2::Composition::Device);
     }
+
+    auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+    error = hwcLayer->setBuffer(mActiveBuffer->handle, acquireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
+                mActiveBuffer->handle, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+    }
 }
 #else
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
@@ -844,6 +832,7 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
             }
         }
     }
+    setAcquiredFenceIfBlit(fenceFd, layer);
     layer.setAcquireFenceFd(fenceFd);
 }
 
@@ -875,21 +864,21 @@ Rect Layer::getPosition(
 // drawing...
 // ---------------------------------------------------------------------------
 
-void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
+void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) {
     onDraw(hw, clip, false);
 }
 
 void Layer::draw(const sp<const DisplayDevice>& hw,
-        bool useIdentityTransform) const {
+        bool useIdentityTransform) {
     onDraw(hw, Region(hw->bounds()), useIdentityTransform);
 }
 
-void Layer::draw(const sp<const DisplayDevice>& hw) const {
+void Layer::draw(const sp<const DisplayDevice>& hw) {
     onDraw(hw, Region(hw->bounds()), false);
 }
 
 void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
-        bool useIdentityTransform) const
+        bool useIdentityTransform)
 {
     ATRACE_CALL();
 
@@ -934,7 +923,8 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
 
     RenderEngine& engine(mFlinger->getRenderEngine());
 
-    if (!blackOutLayer) {
+    if (!blackOutLayer ||
+            ((hw->getDisplayType() == HWC_DISPLAY_PRIMARY) && canAllowGPUForProtected())) {
         // TODO: we could be more subtle with isFixedSize()
         const bool useFiltering = getFiltering() || needsFiltering(hw) || isFixedSize();
 
@@ -1002,6 +992,16 @@ void Layer::clearWithOpenGL(
     clearWithOpenGL(hw, clip, 0,0,0,0);
 }
 
+void Layer::handleOpenGLDraw(const sp<const DisplayDevice>& /* hw */,
+            Mesh& mesh) const {
+    const State& s(getDrawingState());
+    RenderEngine& engine(mFlinger->getRenderEngine());
+
+    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
+    engine.drawMesh(mesh);
+    engine.disableBlending();
+}
+
 void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
         const Region& /* clip */, bool useIdentityTransform) const {
     const State& s(getDrawingState());
@@ -1022,6 +1022,19 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
      * minimal value)? Or, we could make GL behave like HWC -- but this feel
      * like more of a hack.
      */
+#ifdef QTI_BSP
+    Rect win(s.active.w, s.active.h);
+
+    if (!s.crop.isEmpty()) {
+        win = s.crop;
+    }
+
+    win = s.active.transform.transform(win);
+    win.intersect(hw->getViewport(), &win);
+    win = s.active.transform.inverse().transform(win);
+    win.intersect(Rect(s.active.w, s.active.h), &win);
+    win = reduce(win, s.activeTransparentRegion);
+#else
     Rect win(computeBounds());
 
     if (!s.finalCrop.isEmpty()) {
@@ -1034,7 +1047,7 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
             win.clear();
         }
     }
-
+#endif
     float left   = float(win.left)   / float(s.active.w);
     float top    = float(win.top)    / float(s.active.h);
     float right  = float(win.right)  / float(s.active.w);
@@ -1048,10 +1061,7 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
     texCoords[2] = vec2(right, 1.0f - bottom);
     texCoords[3] = vec2(right, 1.0f - top);
 
-    RenderEngine& engine(mFlinger->getRenderEngine());
-    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
-    engine.drawMesh(mMesh);
-    engine.disableBlending();
+    handleOpenGLDraw(hw, mMesh);
 }
 
 #ifdef USE_HWC2
@@ -1192,21 +1202,58 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
     if (!s.crop.isEmpty()) {
         win.intersect(s.crop, &win);
     }
-    // subtract the transparent region and snap to the bounds
+#ifdef QTI_BSP
+    win = s.active.transform.transform(win);
+    win.intersect(hw->getViewport(), &win);
+    win = s.active.transform.inverse().transform(win);
+    win.intersect(Rect(s.active.w, s.active.h), &win);
     win = reduce(win, s.activeTransparentRegion);
 
+    const Transform bufferOrientation(mCurrentTransform);
+    Transform transform(tr * s.active.transform * bufferOrientation);
+    if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
+        uint32_t invTransform =  DisplayDevice::getPrimaryDisplayOrientationTransform();
+         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+              invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                      NATIVE_WINDOW_TRANSFORM_FLIP_H;
+         }
+          transform = Transform(invTransform) * transform;
+    }
+    const uint32_t orientation = transform.getOrientation();
+    if (!(orientation | mCurrentTransform | mTransformHint)) {
+        if (!useIdentityTransform) {
+            win = s.active.transform.transform(win);
+            win.intersect(hw->getViewport(), &win);
+        }
+    }
+#else
+    win = reduce(win, s.activeTransparentRegion);
+#endif
+
+
+
+    // subtract the transparent region and snap to the bounds
+
     vec2 lt = vec2(win.left, win.top);
     vec2 lb = vec2(win.left, win.bottom);
     vec2 rb = vec2(win.right, win.bottom);
     vec2 rt = vec2(win.right, win.top);
 
     if (!useIdentityTransform) {
-        lt = s.active.transform.transform(lt);
-        lb = s.active.transform.transform(lb);
-        rb = s.active.transform.transform(rb);
-        rt = s.active.transform.transform(rt);
+#ifdef QTI_BSP
+        if (orientation | mCurrentTransform | mTransformHint) {
+            lt = s.active.transform.transform(lt);
+            lb = s.active.transform.transform(lb);
+            rb = s.active.transform.transform(rb);
+            rt = s.active.transform.transform(rt);
+        }
+#else
+            lt = s.active.transform.transform(lt);
+            lb = s.active.transform.transform(lb);
+            rb = s.active.transform.transform(rb);
+            rt = s.active.transform.transform(rt);
+#endif
     }
-
     if (!s.finalCrop.isEmpty()) {
         boundPoint(&lt, s.finalCrop);
         boundPoint(&lb, s.finalCrop);
@@ -1435,11 +1482,9 @@ uint32_t Layer::doTransaction(uint32_t flags) {
                 c.requested.w, c.requested.h);
     }
 
+    const bool resizePending = (c.requested.w != c.active.w) ||
+            (c.requested.h != c.active.h);
     if (!isFixedSize()) {
-
-        const bool resizePending = (c.requested.w != c.active.w) ||
-                                   (c.requested.h != c.active.h);
-
         if (resizePending && mSidebandStream == NULL) {
             // don't let Layer::doTransaction update the drawing state
             // if we have a pending resize, unless we are in fixed-size mode.
@@ -1462,7 +1507,17 @@ uint32_t Layer::doTransaction(uint32_t flags) {
     // this is used by Layer, which special cases resizes.
     if (flags & eDontUpdateGeometryState)  {
     } else {
-        c.active = c.requested;
+        Layer::State& editCurrentState(getCurrentState());
+        if (mFreezePositionUpdates) {
+            float tx = c.active.transform.tx();
+            float ty = c.active.transform.ty();
+            c.active = c.requested;
+            c.active.transform.set(tx, ty);
+            editCurrentState.active = c.active;
+        } else {
+            editCurrentState.active = editCurrentState.requested;
+            c.active = c.requested;
+        }
     }
 
     if (s.active != c.active) {
@@ -1509,7 +1564,7 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) {
     return android_atomic_or(flags, &mTransactionFlags);
 }
 
-bool Layer::setPosition(float x, float y) {
+bool Layer::setPosition(float x, float y, bool immediate) {
     if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
         return false;
     mCurrentState.sequence++;
@@ -1518,12 +1573,16 @@ bool Layer::setPosition(float x, float y) {
     // we want to apply the position portion of the transform matrix immediately,
     // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
     mCurrentState.requested.transform.set(x, y);
-    mCurrentState.active.transform.set(x, y);
+    if (immediate && !mFreezePositionUpdates) {
+        mCurrentState.active.transform.set(x, y);
+    }
+    mFreezePositionUpdates = mFreezePositionUpdates || !immediate;
 
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
+
 bool Layer::setLayer(uint32_t z) {
     if (mCurrentState.z == z)
         return false;
@@ -1533,6 +1592,14 @@ bool Layer::setLayer(uint32_t z) {
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
+bool Layer::setBlur(uint8_t blur) {
+    if (mCurrentState.blur == blur)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.blur = blur;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
 bool Layer::setSize(uint32_t w, uint32_t h) {
     if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
         return false;
@@ -1603,6 +1670,17 @@ bool Layer::setOverrideScalingMode(int32_t scalingMode) {
     if (scalingMode == mOverrideScalingMode)
         return false;
     mOverrideScalingMode = scalingMode;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
+bool Layer::setColor(uint32_t color) {
+    if (mCurrentState.color == color)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.color = color;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
@@ -1966,11 +2044,16 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
 
             // Remove any stale buffers that have been dropped during
             // updateTexImage
-            while (mQueueItems[0].mFrameNumber != currentFrameNumber) {
+            while ((mQueuedFrames > 0) && (mQueueItems[0].mFrameNumber != currentFrameNumber)) {
                 mQueueItems.removeAt(0);
                 android_atomic_dec(&mQueuedFrames);
             }
 
+            if (mQueuedFrames == 0) {
+                ALOGE("[%s] mQueuedFrames is zero !!", mName.string());
+                return outDirtyRegion;
+            }
+
             mQueueItems.removeAt(0);
         }
 
@@ -2022,6 +2105,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
             if (bufWidth != uint32_t(oldActiveBuffer->width) ||
                 bufHeight != uint32_t(oldActiveBuffer->height)) {
                 recomputeVisibleRegions = true;
+                mFreezePositionUpdates = false;
             }
         }
 
@@ -2077,7 +2161,7 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
     return usage;
 }
 
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) {
     uint32_t orientation = 0;
     if (!mFlinger->mDebugDisableTransformHint) {
         // The transform hint is used to improve performance, but we can
@@ -2090,6 +2174,7 @@ void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
         }
     }
     mSurfaceFlingerConsumer->setTransformHint(orientation);
+    mTransformHint = orientation;
 }
 
 // ----------------------------------------------------------------------------
@@ -2116,9 +2201,9 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
             "crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
 #ifdef USE_HWC2
-            "alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
+            "alpha=%.3f, blur=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
 #else
-            "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
+            "alpha=0x%02x, blur=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
 #endif
             "      client=%p\n",
             s.layerStack, s.z, s.active.transform.tx(), s.active.transform.ty(), s.active.w, s.active.h,
@@ -2127,7 +2212,7 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
             s.finalCrop.left, s.finalCrop.top,
             s.finalCrop.right, s.finalCrop.bottom,
             isOpaque(s), contentDirty,
-            s.alpha, s.flags,
+            s.alpha, s.blur, s.flags,
             s.active.transform[0][0], s.active.transform[0][1],
             s.active.transform[1][0], s.active.transform[1][1],
             client.get());