乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android Q 色彩(顏色)模式解析(一)

       老匹夫 2019-12-03

      Android 色彩(顏色)模式解析(一)

      Android Q 在系統(tǒng)設(shè)置中提供了可設(shè)置的色彩模式,當(dāng)然這功能很多廠商早就有了~,落后歸落后,我們還是看看Android是怎么實(shí)現(xiàn)的!

      Android Q提供了4種色彩模式:

      • Natural 自然色
      • Boosted 效果增強(qiáng)
      • Saturated 飽和色
      • Adaptive 自動(dòng)調(diào)節(jié)

      下面我們就結(jié)合實(shí)際代碼,看看具體的實(shí)現(xiàn)和流程!

      FrameWork色彩模式的定義及實(shí)現(xiàn)

      為了實(shí)現(xiàn)色彩模式的切換,Android Framework設(shè)計(jì)了ColorDisplayManager及對(duì)應(yīng)的服務(wù),提供可切換的色彩模式和對(duì)應(yīng)的設(shè)置接口。四種色彩模式對(duì)應(yīng)的值如下:

          public static final int COLOR_MODE_NATURAL = 0;
      
          public static final int COLOR_MODE_BOOSTED = 1;
      
          public static final int COLOR_MODE_SATURATED = 2;
      
          public static final int COLOR_MODE_AUTOMATIC = 3;
      復(fù)制代碼

      Settings中通過ColorDisplayManager的setColorMode接口進(jìn)行色彩模式的切換,對(duì)應(yīng)的代碼如下:

      * packages/apps/Settings/src/com/android/settings/display/ColorModePreferenceFragment.java
      
          @Override
          protected boolean setDefaultKey(String key) {
              switch (key) {
                  case KEY_COLOR_MODE_NATURAL:
                      mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL);
                      break;
                  case KEY_COLOR_MODE_BOOSTED:
                      mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED);
                      break;
                  case KEY_COLOR_MODE_SATURATED:
                      mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED);
                      break;
                  case KEY_COLOR_MODE_AUTOMATIC:
                      mColorDisplayManager.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC);
                      break;
              }
              return true;
          }
      復(fù)制代碼

      在ColorDisplayManager中,設(shè)計(jì)了一個(gè)內(nèi)部類ColorDisplayManagerInternal,通過內(nèi)部類和對(duì)應(yīng)的系統(tǒng)服務(wù)COLOR_DISPLAY_SERVICE進(jìn)行交互。

      *  frameworks/base/core/java/android/hardware/display/ColorDisplayManager.java
      
          public void setColorMode(int colorMode) {
              mManager.setColorMode(colorMode);
          }
      復(fù)制代碼

      對(duì)應(yīng)的服務(wù)實(shí)現(xiàn)如下:

      * frameworks/base/services/core/java/com/android/server/display/color/ColorDisplayService.java
      
          private void setColorModeInternal(@ColorMode int colorMode) {
              if (!isColorModeAvailable(colorMode)) {
                  throw new IllegalArgumentException("Invalid colorMode: " + colorMode);
              }
              System.putIntForUser(getContext().getContentResolver(), System.DISPLAY_COLOR_MODE,
                      colorMode,
                      mCurrentUser);
          }
      復(fù)制代碼

      在色彩顯示服務(wù)中,只是將需要的色彩模式對(duì)應(yīng)的值寫到了,系統(tǒng)設(shè)置的數(shù)據(jù)庫中,鍵值DISPLAY_COLOR_MODE。

      其實(shí),看多了Framework的代碼,我們就會(huì)知道,肯定會(huì)有一個(gè)ContentObserver來監(jiān)聽這個(gè)數(shù)據(jù)的變化的,在ColorDisplayService的setUp函數(shù)中:

          private void setUp() {
              Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);
      
              // Listen for external changes to any of the settings.
              if (mContentObserver == null) {
                  mContentObserver = new ContentObserver(new Handler(DisplayThread.get().getLooper())) {
                      @Override
                      public void onChange(boolean selfChange, Uri uri) {
                          super.onChange(selfChange, uri);
      
                          final String setting = uri == null ? null : uri.getLastPathSegment();
                          if (setting != null) {
                              switch (setting) {
                                  ... ...
                                  case System.DISPLAY_COLOR_MODE:
                                      onDisplayColorModeChanged(getColorModeInternal());
      復(fù)制代碼

      當(dāng)設(shè)置中,切換色彩模式,修改了系統(tǒng)設(shè)置中的DISPLAY_COLOR_MODE值后,這個(gè)observer就會(huì)觸發(fā)DISPLAY_COLOR_MODE的onChange,最后通過onDisplayColorModeChanged函數(shù)來處理。

      * frameworks/base/services/core/java/com/android/server/display/color/ColorDisplayService.java
      
          private void onDisplayColorModeChanged(int mode) {
              if (mode == NOT_SET) {
                  return;
              }
      
              mNightDisplayTintController.cancelAnimator();
              mDisplayWhiteBalanceTintController.cancelAnimator();
      
              if (mNightDisplayTintController.isAvailable(getContext())) {
                  mNightDisplayTintController
                          .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix(mode));
                  mNightDisplayTintController
                          .setMatrix(mNightDisplayTintController.getColorTemperatureSetting());
              }
      
              updateDisplayWhiteBalanceStatus();
      
              final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
              dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
          }
      復(fù)制代碼

      這里涉及到夜光屏和白平衡,說白了,這些的實(shí)現(xiàn)都是跟色彩和亮度有關(guān)。我們先留下夜光屏幕和白平衡,單看色彩模式的流程。色彩模式,通過 DisplayTransformManager 的setColorMode接口繼續(xù)往下傳:

      * frameworks/base/services/core/java/com/android/server/display/color/DisplayTransformManager.java
      
          public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
              if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
                  applySaturation(COLOR_SATURATION_NATURAL);
                  setDisplayColor(DISPLAY_COLOR_MANAGED);
              } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
                  applySaturation(COLOR_SATURATION_BOOSTED);
                  setDisplayColor(DISPLAY_COLOR_MANAGED);
              } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
                  applySaturation(COLOR_SATURATION_NATURAL);
                  setDisplayColor(DISPLAY_COLOR_UNMANAGED);
              } else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
                  applySaturation(COLOR_SATURATION_NATURAL);
                  setDisplayColor(DISPLAY_COLOR_ENHANCED);
              }
              setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix);
      
              updateConfiguration();
      
              return true;
          }
      復(fù)制代碼

      重點(diǎn)來了,前面我們說到的4種色彩模式,主要通過兩個(gè)參數(shù)的調(diào)節(jié)來實(shí)現(xiàn)的

      • Saturation飽和度
        飽和度兩種可選模式:自然模式和增強(qiáng)模式
          private static final float COLOR_SATURATION_NATURAL = 1.0f;
          private static final float COLOR_SATURATION_BOOSTED = 1.1f;
      復(fù)制代碼
      • DisplayColor顯示顏色
        顯示顏色有3種模式:Managed,UnManaged以及增強(qiáng)模式
          private static final int DISPLAY_COLOR_MANAGED = 0;
          private static final int DISPLAY_COLOR_UNMANAGED = 1;
          private static final int DISPLAY_COLOR_ENHANCED = 2;
      復(fù)制代碼

      我們的4中色彩模式:

      ** COLOR_SATURATION_NATURAL COLOR_SATURATION_BOOSTED
      DISPLAY_COLOR_MANAGED 自然色 COLOR_MODE_NATURAL 效果增強(qiáng) COLOR_MODE_BOOSTED
      DISPLAY_COLOR_UNMANAGED 飽和色 COLOR_MODE_SATURATED
      DISPLAY_COLOR_ENHANCED 自動(dòng)調(diào)節(jié) COLOR_MODE_AUTOMATIC

      這兩個(gè)參數(shù)的設(shè)置是通過binder直接設(shè)置到SurfaceFlinger的,對(duì)應(yīng)的Binder 命令分別為SURFACE_FLINGER_TRANSACTION_SATURATIONSURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR。相應(yīng)的代碼如下:
      飽和度的設(shè)置通過applySaturation函數(shù)

      * frameworks/base/services/core/java/com/android/server/display/color/DisplayTransformManager.java
      
          private void applySaturation(float saturation) {
              SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, Float.toString(saturation));
              final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
              if (flinger != null) {
                  final Parcel data = Parcel.obtain();
                  data.writeInterfaceToken("android.ui.ISurfaceComposer");
                  data.writeFloat(saturation);
                  try {
                      flinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
                  } catch (RemoteException ex) {
                      Slog.e(TAG, "Failed to set saturation", ex);
                  } finally {
                      data.recycle();
                  }
              }
          }
      復(fù)制代碼

      顯示顏色的設(shè)置通過setDisplayColor函數(shù)

          private void setDisplayColor(int color) {
              SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, Integer.toString(color));
              final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
              if (flinger != null) {
                  final Parcel data = Parcel.obtain();
                  data.writeInterfaceToken("android.ui.ISurfaceComposer");
                  data.writeInt(color);
                  try {
                      flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
                  } catch (RemoteException ex) {
                      Slog.e(TAG, "Failed to set display color", ex);
                  } finally {
                      data.recycle();
                  }
              }
          }
      復(fù)制代碼

      小結(jié)一下,Android提供了4種色彩模式:自然色,效果增強(qiáng),飽和色和自動(dòng)調(diào)節(jié)。而Framework中,是通過兩個(gè)參數(shù)來實(shí)現(xiàn)的:飽和度和顯示顏色,具體實(shí)現(xiàn),,,往下看!

      SurfaceFlinger對(duì)色彩模式的支持和實(shí)現(xiàn)

      通過前面的分析,我們其實(shí)只需關(guān)心飽和度和顯示顏色!SurfaceFlinger中,飽和度用飽和因子mGlobalSaturationFactor來定義,顯示顏色用mDisplayColorSetting進(jìn)行描述。

      status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                          uint32_t flags) {
          ... ...
          status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
          if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
              ... ...
              int n;
              switch (code) {
                  ... ...
                  case 1022: { // Set saturation boost
                      Mutex::Autolock _l(mStateLock);
                      mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f));
      
                      updateColorMatrixLocked();
      
                      ALOGE("xm-gfx: 1022 mGlobalSaturationFactor:%f
      ", mGlobalSaturationFactor);
                      return NO_ERROR;
                  }
                  case 1023: { // Set native mode
                      mDisplayColorSetting = static_cast<DisplayColorSetting>(data.readInt32());
                      invalidateHwcGeometry();
                      repaintEverything();
                      ALOGE("xm-gfx: 1023 mDisplayColorSetting:%d
      ", mDisplayColorSetting);
                      return NO_ERROR;
                  }
      復(fù)制代碼

      飽和因子是一個(gè)float值,默認(rèn)為1.0,系統(tǒng)最初始的值,可以通過屬性persist.sys.sf.color_saturation進(jìn)行設(shè)置。飽和因子影響到的是顯示的顏色矩陣,具體的算法在這個(gè)函數(shù)中:

      void SurfaceFlinger::updateColorMatrixLocked() {
          mat4 colorMatrix;
          if (mGlobalSaturationFactor != 1.0f) {
              // Rec.709 luma coefficients
              float3 luminance{0.213f, 0.715f, 0.072f};
              luminance *= 1.0f - mGlobalSaturationFactor;
              mat4 saturationMatrix = mat4(
                  vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
                  vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
                  vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
                  vec4{0.0f, 0.0f, 0.0f, 1.0f}
              );
              colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
          } else {
              colorMatrix = mClientColorMatrix * mDaltonizer();
          }
      
          if (mCurrentState.colorMatrix != colorMatrix) {
              mCurrentState.colorMatrix = colorMatrix;
              mCurrentState.colorMatrixChanged = true;
              setTransactionFlags(eTransactionNeeded);
          }
      }
      復(fù)制代碼

      根據(jù)飽和因子,生成一個(gè)飽和度的矩陣saturationMatrix,再和其他的顏色矩陣相乘,得到需要的矩陣。至于這個(gè)矩陣colorMatrix怎么生效的,我們稍后再看!

      顯示顏色mDisplayColorSetting,最后值可以通過persist.sys.sf.native_mode屬性來設(shè)置。

      看屏幕是否支持顏色管理

      SurfaceFlinger定義useColorManagement來描述SurfaceFlinger是否管理顏色。

      bool use_color_management(bool defaultValue) {
          auto tmpuseColorManagement = SurfaceFlingerProperties::use_color_management();
          auto tmpHasHDRDisplay = SurfaceFlingerProperties::has_HDR_display();
          auto tmpHasWideColorDisplay = SurfaceFlingerProperties::has_wide_color_display();
      
          auto tmpuseColorManagementVal = tmpuseColorManagement.has_value() ? *tmpuseColorManagement :
              defaultValue;
          auto tmpHasHDRDisplayVal = tmpHasHDRDisplay.has_value() ? *tmpHasHDRDisplay :
              defaultValue;
          auto tmpHasWideColorDisplayVal = tmpHasWideColorDisplay.has_value() ? *tmpHasWideColorDisplay :
              defaultValue;
      
          return tmpuseColorManagementVal || tmpHasHDRDisplayVal || tmpHasWideColorDisplayVal;
      }
      復(fù)制代碼

      第一次看這個(gè)代碼的時(shí)候比較奇怪,其實(shí)這個(gè)就是對(duì)屬性訪問的一個(gè)封裝,對(duì)應(yīng)的屬性訪問和接口用sysprop進(jìn)行描述,定義在SurfaceFlingerProperties.sysprop中,上述3個(gè)變量對(duì)應(yīng)的3個(gè)屬性如下:

      ro.surface_flinger.use_color_management
      ro.surface_flinger.has_HDR_display
      ro.surface_flinger.has_wide_color_display
      復(fù)制代碼

      我們來看一個(gè)屬性接口的描述:

      * frameworks/native/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
      prop {
          api_name: "has_wide_color_display"
          type: Boolean
          scope: Internal
          access: Readonly
          prop_name: "ro.surface_flinger.has_wide_color_display"
      }
      復(fù)制代碼

      sysprop會(huì)被編譯成cpp文件!生產(chǎn)的文件在:

      out/soong/.intermediates/frameworks/native/services/surfaceflinger/sysprop/libSurfaceFlingerProperties/android_arm64_armv8-a_core_static/gen/sysprop/SurfaceFlingerProperties.sysprop.cpp
      復(fù)制代碼

      has_wide_color_display對(duì)應(yīng)的實(shí)現(xiàn)如下:

      std::optional<bool> has_wide_color_display() {
          return GetProp<std::optional<bool>>("ro.surface_flinger.has_wide_color_display");
      }
      復(fù)制代碼

      屏幕的ColorProfile

      顏色管理,是針對(duì)屏幕的,不是對(duì)單個(gè)Layer的!每次一次開始合成時(shí),都會(huì)去做屏幕顏色的處理,在calculateWorkingSet函數(shù)中。

      void SurfaceFlinger::calculateWorkingSet() {
          ... ...
      
          // Set the per-frame data
          for (const auto& [token, displayDevice] : mDisplays) {
              auto display = displayDevice->getCompositionDisplay();
              const auto displayId = display->getId();
              if (!displayId) {
                  continue;
              }
              auto* profile = display->getDisplayColorProfile();
      
              if (mDrawingState.colorMatrixChanged) {
                  display->setColorTransform(mDrawingState.colorMatrix);
              }
              Dataspace targetDataspace = Dataspace::UNKNOWN;
              if (useColorManagement) {
                  ColorMode colorMode;
                  RenderIntent renderIntent;
                  pickColorMode(displayDevice, &colorMode, &targetDataspace, &renderIntent);
                  display->setColorMode(colorMode, targetDataspace, renderIntent);
              }
      復(fù)制代碼

      SurfaceFlinger中,Profile封裝了傳輸給顯示屏幕顏色的所有的狀態(tài)和功能!ColorMode只是顯示屏眾多特性中的一個(gè)。SurfaceFlinger中用ColorModeValue進(jìn)行描述:

      * frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h
      
          struct ColorModeValue {
              ui::Dataspace dataspace;
              ui::ColorMode colorMode;
              ui::RenderIntent renderIntent;
          };
      復(fù)制代碼

      ui的定義在hardware/interfaces/graphics/common中。目前是1.3版本!

      我們來看看幾個(gè)比較常用的:

      • Dataspace
      * hardware/interfaces/graphics/common/1.0/types.hal
      
      @export(name="android_dataspace_t", value_prefix="HAL_DATASPACE_")
      enum Dataspace : int32_t {
          /**
           * Default-assumption data space, when not explicitly specified.
           *
           * It is safest to assume the buffer is an image with sRGB primaries and
           * encoding ranges, but the consumer and/or the producer of the data may
           * simply be using defaults. No automatic gamma transform should be
           * expected, except for a possible display gamma transform when drawn to a
           * screen.
           */
          UNKNOWN = 0x0,
      
          ... ...
      
          /**
           * Transfer characteristic curve:
           *  E = L
           *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
           *      E - corresponding electrical signal
           */
          TRANSFER_LINEAR = 1 << TRANSFER_SHIFT,
      
          /**
           * Transfer characteristic curve:
           *
           * E = 1.055 * L^(1/2.4) - 0.055  for 0.0031308 <= L <= 1
           *   = 12.92 * L                  for 0 <= L < 0.0031308
           *     L - luminance of image 0 <= L <= 1 for conventional colorimetry
           *     E - corresponding electrical signal
           */
          TRANSFER_SRGB = 2 << TRANSFER_SHIFT,
          ... ...
      
          /**
           * sRGB gamma encoding:
           *
           * The red, green and blue components are stored in sRGB space, and
           * converted to linear space when read, using the SRGB transfer function
           * for each of the R, G and B components. When written, the inverse
           * transformation is performed.
           *
           * The alpha component, if present, is always stored in linear space and
           * is left unmodified when read or written.
           *
           * Use full range and BT.709 standard.
           */
          SRGB = 0x201, // deprecated, use V0_SRGB
      
          V0_SRGB = STANDARD_BT709 | TRANSFER_SRGB | RANGE_FULL,
      
          ... ...
      
          /**
           * Display P3
           *
           * Use same primaries and white-point as DCI-P3
           * but sRGB transfer function.
           */
          DISPLAY_P3 = STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_FULL,
      };
      
      復(fù)制代碼
      • ColorMode
      * hardware/interfaces/graphics/common/1.0/types.hal
      
      @export(name="android_color_mode_t", value_prefix="HAL_COLOR_MODE_")
      enum ColorMode : int32_t {
          /**
           * DEFAULT is the "native" gamut of the display.
           * White Point: Vendor/OEM defined
           * Panel Gamma: Vendor/OEM defined (typically 2.2)
           * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
           */
          NATIVE = 0,
      
          ... ...
      
          /**
           * SRGB corresponds with display settings that implement
           * the sRGB color space. Uses the same primaries as ITU-R Recommendation
           * BT.709
           * Rendering Intent: Colorimetric
           * Primaries:
           *                  x       y
           *  green           0.300   0.600
           *  blue            0.150   0.060
           *  red             0.640   0.330
           *  white (D65)     0.3127  0.3290
           *
           * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
           *
           *  if Vnonlinear ≤ 0.03928
           *    Vlinear = Vnonlinear / 12.92
           *  else
           *    Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
           *
           * PC/Internet (sRGB) Gamma Correction (GC):
           *
           *  if Vlinear ≤ 0.0031308
           *    Vnonlinear = 12.92 * Vlinear
           *  else
           *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
           */
          SRGB = 7,
      
          ... ...
      
          /**
           * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
           * the D65 white point and the SRGB transfer functions.
           * Rendering Intent: Colorimetric
           * Primaries:
           *                  x       y
           *  green           0.265   0.690
           *  blue            0.150   0.060
           *  red             0.680   0.320
           *  white (D65)     0.3127  0.3290
           *
           * PC/Internet (sRGB) Gamma Correction (GC):
           *
           *  if Vlinear ≤ 0.0030186
           *    Vnonlinear = 12.92 * Vlinear
           *  else
           *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
           *
           * Note: In most cases sRGB transfer function will be fine.
           */
          DISPLAY_P3 = 9
      };
      復(fù)制代碼
      • RenderIntent
      * hardware/interfaces/graphics/common/1.1/types.hal
      
      @export(name="android_render_intent_v1_1_t", value_prefix="HAL_RENDER_INTENT_",
              export_parent="false")
      enum RenderIntent : int32_t {
          /**
           * Colors in the display gamut are unchanged. Colors out of the display
           * gamut are hard-clipped.
           *
           * This implies that the display must have been calibrated unless
           * ColorMode::NATIVE is the only supported color mode.
           */
          COLORIMETRIC = 0,
      
          /**
           * Enhance colors that are in the display gamut. Colors out of the display
           * gamut are hard-clipped.
           *
           * The enhancement typically picks the biggest standard color space (e.g.
           * DCI-P3) that is narrower than the display gamut and stretches it to the
           * display gamut. The stretching is recommended to preserve skin tones.
           */
          ENHANCE = 1,
      
          /**
           * Tone map high-dynamic-range colors to the display's dynamic range. The
           * dynamic range of the colors are communicated separately. After tone
           * mapping, the mapping to the display gamut is as defined in
           * COLORIMETRIC.
           */
          TONE_MAP_COLORIMETRIC = 2,
      
          /**
           * Tone map high-dynamic-range colors to the display's dynamic range. The
           * dynamic range of the colors are communicated separately. After tone
           * mapping, the mapping to the display gamut is as defined in ENHANCE.
           *
           * The tone mapping step and the enhancing step must match
           * TONE_MAP_COLORIMETRIC and ENHANCE respectively when they are also
           * supported.
           */
          TONE_MAP_ENHANCE = 3,
      
          /*
           * Vendors are recommended to use 0x100 - 0x1FF for their own values, and
           * that must be done with subtypes defined by vendor extensions.
           */
      };
      復(fù)制代碼

      SurfaceFlinger設(shè)置ColorMode的流程

      // Pick the ColorMode / Dataspace for the display device.
      void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode* outMode,
                                         Dataspace* outDataSpace, RenderIntent* outRenderIntent) const {
          if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) {
              *outMode = ColorMode::NATIVE;
              *outDataSpace = Dataspace::UNKNOWN;
              *outRenderIntent = RenderIntent::COLORIMETRIC;
              return;
          }
      
          Dataspace hdrDataSpace;
          Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace);
      
          auto* profile = display->getCompositionDisplay()->getDisplayColorProfile();
      
          switch (mForceColorMode) {
              case ColorMode::SRGB:
                  bestDataSpace = Dataspace::V0_SRGB;
                  break;
              case ColorMode::DISPLAY_P3:
                  bestDataSpace = Dataspace::DISPLAY_P3;
                  break;
              default:
                  break;
          }
      
          // respect hdrDataSpace only when there is no legacy HDR support
          const bool isHdr =
                  hdrDataSpace != Dataspace::UNKNOWN && !profile->hasLegacyHdrSupport(hdrDataSpace);
          if (isHdr) {
              bestDataSpace = hdrDataSpace;
          }
      
          RenderIntent intent;
          switch (mDisplayColorSetting) {
              case DisplayColorSetting::MANAGED:
              case DisplayColorSetting::UNMANAGED:
                  intent = isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC;
                  break;
              case DisplayColorSetting::ENHANCED:
                  intent = isHdr ? RenderIntent::TONE_MAP_ENHANCE : RenderIntent::ENHANCE;
                  break;
              default: // vendor display color setting
                  intent = static_cast<RenderIntent>(mDisplayColorSetting);
                  break;
          }
      
          profile->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
      }
      復(fù)制代碼

      可見,在選擇ColorMode時(shí),獲取ColorMode,DataSpace,和RenderIntent。

      首先來看,bestDataSpace的獲取,實(shí)現(xiàn)函數(shù)如下:

      // Returns a data space that fits all visible layers.  The returned data space
      // can only be one of
      //  - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
      //  - Dataspace::DISPLAY_P3
      //  - Dataspace::DISPLAY_BT2020
      // The returned HDR data space is one of
      //  - Dataspace::UNKNOWN
      //  - Dataspace::BT2020_HLG
      //  - Dataspace::BT2020_PQ
      Dataspace SurfaceFlinger::getBestDataspace(const sp<const DisplayDevice>& display,
                                                 Dataspace* outHdrDataSpace) const {
          Dataspace bestDataSpace = Dataspace::V0_SRGB;
          *outHdrDataSpace = Dataspace::UNKNOWN;
      
          for (const auto& layer : display->getVisibleLayersSortedByZ()) {
              switch (layer->getDataSpace()) {
                  case Dataspace::V0_SCRGB:
                  case Dataspace::V0_SCRGB_LINEAR:
                  case Dataspace::BT2020:
                  case Dataspace::BT2020_ITU:
                  case Dataspace::BT2020_LINEAR:
                  case Dataspace::DISPLAY_BT2020:
                      bestDataSpace = Dataspace::DISPLAY_BT2020;
                      break;
                  case Dataspace::DISPLAY_P3:
                      bestDataSpace = Dataspace::DISPLAY_P3;
                      break;
                  case Dataspace::BT2020_PQ:
                  case Dataspace::BT2020_ITU_PQ:
                      bestDataSpace = Dataspace::DISPLAY_P3;
                      *outHdrDataSpace = Dataspace::BT2020_PQ;
                      break;
                  case Dataspace::BT2020_HLG:
                  case Dataspace::BT2020_ITU_HLG:
                      bestDataSpace = Dataspace::DISPLAY_P3;
                      // When there's mixed PQ content and HLG content, we set the HDR
                      // data space to be BT2020_PQ and convert HLG to PQ.
                      if (*outHdrDataSpace == Dataspace::UNKNOWN) {
                          *outHdrDataSpace = Dataspace::BT2020_HLG;
                      }
                      break;
                  default:
                      break;
              }
          }
      
          return bestDataSpace;
      }
      復(fù)制代碼

      說說實(shí)話,這個(gè)算法沒有“看懂”。這里采用一個(gè)for循環(huán),檢查所有的Layer,也就是說bestDataSpace會(huì)被后面的Layer不斷的覆蓋… …感覺這段法“看不懂”… Anyway,這里將選一個(gè)最合適的 bestDataSpace,并且去check有沒有HDR的space hdrDataSpace。

      再回來看pickColorMode函數(shù):

      • 可以人為的指定dataspace,通過mForceColorMode:
          property_get("persist.sys.sf.color_mode", value, "0");
          mForceColorMode = static_cast<ColorMode>(atoi(value));
      復(fù)制代碼
      • 如果是Hdr,將使用HDR的Database。

      • 根據(jù)上層給下來的mDisplayColorSetting,確定 RenderIntent。

      RenderIntent isHdr Normal
      MANAGED TONE_MAP_COLORIMETRIC COLORIMETRIC
      UNMANAGED TONE_MAP_COLORIMETRIC COLORIMETRIC
      ENHANCED TONE_MAP_ENHANCE ENHANCE
      void DisplayColorProfile::getBestColorMode(Dataspace dataspace, RenderIntent intent,
                                                 Dataspace* outDataspace, ColorMode* outMode,
                                                 RenderIntent* outIntent) const {
          auto iter = mColorModes.find(getColorModeKey(dataspace, intent));
          if (iter != mColorModes.end()) {
              *outDataspace = iter->second.dataspace;
              *outMode = iter->second.colorMode;
              *outIntent = iter->second.renderIntent;
          } else {
              // this is unexpected on a WCG display
              if (hasWideColorGamut()) {
                  ALOGE("map unknown (%s)/(%s) to default color mode",
                        dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
                        decodeRenderIntent(intent).c_str());
              }
      
              *outDataspace = Dataspace::UNKNOWN;
              *outMode = ColorMode::NATIVE;
              *outIntent = RenderIntent::COLORIMETRIC;
          }
      }
      復(fù)制代碼

      也就是從 mColorModes 中選取一個(gè)合適的模式!~ mColorModes從哪兒來的?其實(shí),添加屏幕的時(shí)候,就會(huì)去初始化這些參數(shù),在DisplayColorProfile的初始函數(shù)中:

      * /frameworks/native/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp
      
      DisplayColorProfile::DisplayColorProfile(DisplayColorProfileCreationArgs&& args)
            : mHasWideColorGamut(args.hasWideColorGamut),
              mSupportedPerFrameMetadata(args.supportedPerFrameMetadata) {
          populateColorModes(args.hwcColorModes);
      
          std::vector<ui::Hdr> types = args.hdrCapabilities.getSupportedHdrTypes();
          for (ui::Hdr hdrType : types) {
              switch (hdrType) {
                  case ui::Hdr::HDR10_PLUS:
                      mHasHdr10Plus = true;
                      break;
                  case ui::Hdr::HDR10:
                      mHasHdr10 = true;
                      break;
                  case ui::Hdr::HLG:
                      mHasHLG = true;
                      break;
                  case ui::Hdr::DOLBY_VISION:
                      mHasDolbyVision = true;
                      break;
                  default:
                      ALOGE("UNKNOWN HDR capability: %d", static_cast<int32_t>(hdrType));
              }
          }
      
          float minLuminance = args.hdrCapabilities.getDesiredMinLuminance();
          float maxLuminance = args.hdrCapabilities.getDesiredMaxLuminance();
          float maxAverageLuminance = args.hdrCapabilities.getDesiredMaxAverageLuminance();
      
          minLuminance = minLuminance <= 0.0 ? sDefaultMinLumiance : minLuminance;
          maxLuminance = maxLuminance <= 0.0 ? sDefaultMaxLumiance : maxLuminance;
          maxAverageLuminance = maxAverageLuminance <= 0.0 ? sDefaultMaxLumiance : maxAverageLuminance;
          if (args.hasWideColorGamut) {
              // insert HDR10/HLG as we will force client composition for HDR10/HLG
              // layers
              if (!hasHDR10Support()) {
                  types.push_back(ui::Hdr::HDR10);
              }
      
              if (!hasHLGSupport()) {
                  types.push_back(ui::Hdr::HLG);
              }
          }
      
          mHdrCapabilities = HdrCapabilities(types, maxLuminance, maxAverageLuminance, minLuminance);
      }
      復(fù)制代碼

      注意這個(gè)args參數(shù),從哪里來的,在SurfaceFlinger添加DisplayDevice時(shí),給的參數(shù)!

      sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
              const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId,
              const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface,
              const sp<IGraphicBufferProducer>& producer) {
          DisplayDeviceCreationArgs creationArgs(this, displayToken, displayId);
          creationArgs.sequenceId = state.sequenceId;
          creationArgs.isVirtual = state.isVirtual();
          creationArgs.isSecure = state.isSecure;
          creationArgs.displaySurface = dispSurface;
          creationArgs.hasWideColorGamut = false;
          creationArgs.supportedPerFrameMetadata = 0;
      
          const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked();
          creationArgs.isPrimary = isInternalDisplay;
      
          if (useColorManagement && displayId) {
              std::vector<ColorMode> modes = getHwComposer().getColorModes(*displayId);
              for (ColorMode colorMode : modes) {
                  if (isWideColorMode(colorMode)) {
                      creationArgs.hasWideColorGamut = true;
                  }
      
                  std::vector<RenderIntent> renderIntents =
                          getHwComposer().getRenderIntents(*displayId, colorMode);
                  creationArgs.hwcColorModes.emplace(colorMode, renderIntents);
              }
          }
      
          if (displayId) {
              getHwComposer().getHdrCapabilities(*displayId, &creationArgs.hdrCapabilities);
              creationArgs.supportedPerFrameMetadata =
                      getHwComposer().getSupportedPerFrameMetadata(*displayId);
          }
      
          auto nativeWindowSurface = getFactory().createNativeWindowSurface(producer);
          auto nativeWindow = nativeWindowSurface->getNativeWindow();
          creationArgs.nativeWindow = nativeWindow;
      
          // Make sure that composition can never be stalled by a virtual display
          // consumer that isn't processing buffers fast enough. We have to do this
          // here, in case the display is composed entirely by HWC.
          if (state.isVirtual()) {
              nativeWindow->setSwapInterval(nativeWindow.get(), 0);
          }
      
          creationArgs.displayInstallOrientation =
                  isInternalDisplay ? primaryDisplayOrientation : DisplayState::eOrientationDefault;
      
          // virtual displays are always considered enabled
          creationArgs.initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
      
          sp<DisplayDevice> display = getFactory().createDisplayDevice(std::move(creationArgs));
      
          if (maxFrameBufferAcquiredBuffers >= 3) {
              nativeWindowSurface->preallocateBuffers();
          }
      
          ColorMode defaultColorMode = ColorMode::NATIVE;
          Dataspace defaultDataSpace = Dataspace::UNKNOWN;
          if (display->hasWideColorGamut()) {
              defaultColorMode = ColorMode::SRGB;
              defaultDataSpace = Dataspace::V0_SRGB;
          }
          display->getCompositionDisplay()->setColorMode(defaultColorMode, defaultDataSpace,
                                                         RenderIntent::COLORIMETRIC);
          if (!state.isVirtual()) {
              LOG_ALWAYS_FATAL_IF(!displayId);
              display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId));
          }
      
          display->setLayerStack(state.layerStack);
          display->setProjection(state.orientation, state.viewport, state.frame);
          display->setDisplayName(state.displayName);
      
          return display;
      }
      復(fù)制代碼

      ColorModes是在populateColorModes函數(shù)中添加的:

      void DisplayColorProfile::populateColorModes(
              const DisplayColorProfileCreationArgs::HwcColorModes& hwcColorModes) {
          if (!hasWideColorGamut()) {
              return;
          }
      
          // collect all known SDR render intents
          std::unordered_set<RenderIntent> sdrRenderIntents(sSdrRenderIntents.begin(),
                                                            sSdrRenderIntents.end());
          auto iter = hwcColorModes.find(ColorMode::SRGB);
          if (iter != hwcColorModes.end()) {
              for (auto intent : iter->second) {
                  sdrRenderIntents.insert(intent);
              }
          }
      
          // add all known SDR combinations
          for (auto intent : sdrRenderIntents) {
              for (auto mode : sSdrColorModes) {
                  addColorMode(hwcColorModes, mode, intent);
              }
          }
      
          // collect all known HDR render intents
          std::unordered_set<RenderIntent> hdrRenderIntents(sHdrRenderIntents.begin(),
                                                            sHdrRenderIntents.end());
          iter = hwcColorModes.find(ColorMode::BT2100_PQ);
          if (iter != hwcColorModes.end()) {
              for (auto intent : iter->second) {
                  hdrRenderIntents.insert(intent);
              }
          }
      
          // add all known HDR combinations
          for (auto intent : hdrRenderIntents) {
              for (auto mode : sHdrColorModes) {
                  addColorMode(hwcColorModes, mode, intent);
              }
          }
      }
      復(fù)制代碼

      從這個(gè)函數(shù)來看,目前主要針對(duì)SDR和HDR,系統(tǒng)默認(rèn)支持的RenderIntent如下:

      // ordered list of known SDR render intents
      const std::array<RenderIntent, 2> sSdrRenderIntents = {
              RenderIntent::ENHANCE,
              RenderIntent::COLORIMETRIC,
      };
      
      // ordered list of known HDR render intents
      const std::array<RenderIntent, 2> sHdrRenderIntents = {
              RenderIntent::TONE_MAP_ENHANCE,
              RenderIntent::TONE_MAP_COLORIMETRIC,
      };
      復(fù)制代碼

      這塊貼的代碼有點(diǎn)多,是為了保存完整性,很多細(xì)節(jié)可以先不看!我們先關(guān)注一下,上層設(shè)置下來的參數(shù),到哪里去了。!這里AddColorMode時(shí),根據(jù)dataspace和renderintent生成key,再將hwc支持的對(duì)應(yīng)的hwcDataspace, hwcColorMode, hwcIntent保存下來。

      回到getBestColorMode函數(shù),上層給下的intent,和dataspace。

          static ColorModeKey getColorModeKey(ui::Dataspace dataspace, ui::RenderIntent intent) {
              return (static_cast<uint64_t>(dataspace) << 32) | static_cast<uint32_t>(intent);
          }
      復(fù)制代碼

      根據(jù)key,去選取hwcDataspace, hwcColorMode, hwcIntent。所以這里的流程梳理下:

      • 屏幕初始化時(shí),獲取屏幕支持的hwcDataspace, hwcColorMode, hwcIntent,轉(zhuǎn)換為SurfaceFlinger中的RenderIntenthedataspace的key來保存
      • 上層設(shè)置的DisplayColorSetting轉(zhuǎn)換為對(duì)應(yīng)的RenderIntent
      • 根據(jù)顯示內(nèi)容,確定最合適的besedataspace
      • 根據(jù)RenderIntent和besedataspace,選取對(duì)應(yīng)的hwcDataspace, hwcColorMode, hwcIntent。

      小結(jié)

      我們這里主要講了上層的顏色管理,接下來看看HAL和底層驅(qū)動(dòng)的具體實(shí)現(xiàn)!

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多