OSDN Git Service

auto determine the density if not provided in surfaceflinger
[android-x86/frameworks-native.git] / services / surfaceflinger / SurfaceFlinger.cpp
index 7363464..d1630dc 100644 (file)
@@ -604,9 +604,18 @@ void SurfaceFlinger::init() {
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
-            ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
-            mVrFlingerRequestsDisplay = requestDisplay;
-            signalTransaction();
+            // This callback is called from the vr flinger dispatch thread. We
+            // need to call signalTransaction(), which requires holding
+            // mStateLock when we're not on the main thread. Acquiring
+            // mStateLock from the vr flinger dispatch thread might trigger a
+            // deadlock in surface flinger (see b/66916578), so post a message
+            // to be handled on the main thread instead.
+            sp<LambdaMessage> message = new LambdaMessage([=]() {
+                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
+                mVrFlingerRequestsDisplay = requestDisplay;
+                signalTransaction();
+            });
+            postMessageAsync(message);
         };
         mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
                                             vrFlingerRequestDisplayCallback);
@@ -647,6 +656,12 @@ void SurfaceFlinger::readPersistentProperties() {
     property_get("persist.sys.sf.color_saturation", value, "1.0");
     mSaturation = atof(value);
     ALOGV("Saturation is set to %.2f", mSaturation);
+
+    property_get("persist.sys.sf.native_mode", value, "0");
+    mForceNativeColorMode = atoi(value) == 1;
+    if (mForceNativeColorMode) {
+        ALOGV("Forcing native color mode");
+    }
 }
 
 void SurfaceFlinger::startBootAnim() {
@@ -693,6 +708,8 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps(
         FrameEvent::DEQUEUE_READY,
         FrameEvent::RELEASE,
     };
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
     if (!getHwComposer().hasCapability(
             HWC2::Capability::PresentFenceIsNotReliable)) {
         outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
@@ -734,21 +751,44 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
     public:
         static int getEmuDensity() {
             return getDensityFromProperty("qemu.sf.lcd_density"); }
-        static int getBuildDensity()  {
-            return getDensityFromProperty("ro.sf.lcd_density"); }
+        static int getBuildDensity(const DisplayInfo& info)  {
+            static int density = getDensityFromProperty("ro.sf.lcd_density");
+#if defined(__i386__) || defined(__x86_64__)
+            if (density == 0) {
+                uint32_t area = info.w * info.h;
+                if (area <= 800 * 480) {
+                    density = 120;
+                } else if (area <= 1024 * 600) {
+                    density = 130;
+                } else if (area < 1024 * 768) {
+                    density = 140;
+                } else if (area < 1920 * 1080) {
+                    density = 160;
+                } else {
+                    density = 240;
+                }
+                ALOGI("auto set density to %d", density);
+            }
+#endif
+            return density;
+        }
     };
 
     configs->clear();
 
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
     for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
         DisplayInfo info = DisplayInfo();
 
         float xdpi = hwConfig->getDpiX();
         float ydpi = hwConfig->getDpiY();
+        info.w = hwConfig->getWidth();
+        info.h = hwConfig->getHeight();
 
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
             // The density of the device is provided by a build property
-            float density = Density::getBuildDensity() / 160.0f;
+            float density = Density::getBuildDensity(info) / 160.0f;
             if (density == 0) {
                 // the build doesn't provide a density -- this is wrong!
                 // use xdpi instead
@@ -763,7 +803,7 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
             info.density = density;
 
             // TODO: this needs to go away (currently needed only by webkit)
-            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+            sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
             info.orientation = hw->getOrientation();
         } else {
             // TODO: where should this value come from?
@@ -772,8 +812,6 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
             info.orientation = 0;
         }
 
-        info.w = hwConfig->getWidth();
-        info.h = hwConfig->getHeight();
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = 1e9 / hwConfig->getVsyncPeriod();
@@ -906,7 +944,12 @@ status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
         return type;
     }
 
-    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+    std::vector<android_color_mode_t> modes;
+    {
+        ConditionalLock _l(mStateLock,
+                std::this_thread::get_id() != mMainThreadId);
+        modes = getHwComposer().getColorModes(type);
+    }
     outColorModes->clear();
     std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
 
@@ -1064,6 +1107,20 @@ void SurfaceFlinger::waitForEvent() {
     mEventQueue.waitMessage();
 }
 
+#ifdef CONSOLE_MANAGER
+void SurfaceFlinger::screenReleased(const sp<IBinder>& display) {
+    // this may be called by a signal handler, we can't do too much in here
+    setPowerMode(display, HWC_POWER_MODE_OFF);
+    signalLayerUpdate();
+}
+
+void SurfaceFlinger::screenAcquired(const sp<IBinder>& display) {
+    // this may be called by a signal handler, we can't do too much in here
+    setPowerMode(display, HWC_POWER_MODE_NORMAL);
+    signalLayerUpdate();
+}
+#endif
+
 void SurfaceFlinger::signalTransaction() {
     mEventQueue.invalidate();
 }
@@ -1217,12 +1274,13 @@ void SurfaceFlinger::createDefaultDisplayDevice() {
                 break;
         }
     }
+    bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode;
     sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
                                              token, fbs, producer, mRenderEngine->getEGLConfig(),
-                                             hasWideColorModes && hasWideColorDisplay);
+                                             useWideColorMode);
     mDisplays.add(token, hw);
     android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
-    if (hasWideColorModes && hasWideColorDisplay) {
+    if (useWideColorMode) {
         defaultColorMode = HAL_COLOR_MODE_SRGB;
     }
     setActiveColorModeInternal(hw, defaultColorMode);
@@ -1287,7 +1345,7 @@ void SurfaceFlinger::onRefreshReceived(int sequenceId,
     if (sequenceId != mComposerSequenceId) {
         return;
     }
-    repaintEverything();
+    repaintEverythingLocked();
 }
 
 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
@@ -1738,6 +1796,10 @@ mat4 SurfaceFlinger::computeSaturationMatrix() const {
 // pickColorMode translates a given dataspace into the best available color mode.
 // Currently only support sRGB and Display-P3.
 android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) const {
+    if (mForceNativeColorMode) {
+        return HAL_COLOR_MODE_NATIVE;
+    }
+
     switch (dataSpace) {
         // treat Unknown as regular SRGB buffer, since that's what the rest of the
         // system expects.
@@ -2572,8 +2634,10 @@ bool SurfaceFlinger::doComposeSurfaces(
         ALOGV("hasClientComposition");
 
 #ifdef USE_HWC2
-        mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
-        mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
+        mRenderEngine->setWideColor(
+                displayDevice->getWideColorSupport() && !mForceNativeColorMode);
+        mRenderEngine->setColorMode(mForceNativeColorMode ?
+                HAL_COLOR_MODE_NATIVE : displayDevice->getActiveColorMode());
 #endif
         if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -3291,7 +3355,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
 
         mVisibleRegionsDirty = true;
         mHasPoweredOff = true;
-        repaintEverything();
+        repaintEverythingLocked();
 
         struct sched_param param = {0};
         param.sched_priority = 1;
@@ -3614,6 +3678,7 @@ void SurfaceFlinger::dumpBufferingStats(String8& result) const {
 
 void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
     result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
+    result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode);
 
     // TODO: print out if wide-color mode is active or not
 
@@ -3935,6 +4000,7 @@ status_t SurfaceFlinger::onTransact(
                 return NO_ERROR;
             }
             case 1005:{ // force transaction
+                Mutex::Autolock _l(mStateLock);
                 setTransactionFlags(
                         eTransactionNeeded|
                         eDisplayTransactionNeeded|
@@ -4066,16 +4132,33 @@ status_t SurfaceFlinger::onTransact(
                 repaintEverything();
                 return NO_ERROR;
             }
+            case 1023: { // Set native mode
+                mForceNativeColorMode = data.readInt32() == 1;
+
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
+            case 1024: { // Is wide color gamut rendering/color management supported?
+                reply->writeBool(hasWideColorDisplay);
+                return NO_ERROR;
+            }
         }
     }
     return err;
 }
 
-void SurfaceFlinger::repaintEverything() {
+void SurfaceFlinger::repaintEverythingLocked() {
     android_atomic_or(1, &mRepaintEverything);
     signalTransaction();
 }
 
+void SurfaceFlinger::repaintEverything() {
+    ConditionalLock _l(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
+    repaintEverythingLocked();
+}
+
 // Checks that the requested width and height are valid and updates them to the display dimensions
 // if they are set to 0
 static status_t updateDimensionsLocked(const sp<const DisplayDevice>& displayDevice,
@@ -4217,8 +4300,9 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
     WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
 
     ANativeWindowBuffer* buffer = nullptr;
-    result = getWindowBuffer(window, reqWidth, reqHeight, hasWideColorDisplay,
-                                      getRenderEngine().usesWideColor(), &buffer);
+    result = getWindowBuffer(window, reqWidth, reqHeight,
+            hasWideColorDisplay && !mForceNativeColorMode,
+            getRenderEngine().usesWideColor(), &buffer);
     if (result != NO_ERROR) {
         return result;
     }
@@ -4320,8 +4404,8 @@ void SurfaceFlinger::renderScreenImplLocked(
     }
 
 #ifdef USE_HWC2
-     engine.setWideColor(hw->getWideColorSupport());
-     engine.setColorMode(hw->getActiveColorMode());
+     engine.setWideColor(hw->getWideColorSupport() && !mForceNativeColorMode);
+     engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : hw->getActiveColorMode());
 #endif
 
     // make sure to clear all GL error flags