910e62b5创建于 1月15日历史提交
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_DISPLAY_UTIL_EDID_PARSER_H_
#define UI_DISPLAY_UTIL_EDID_PARSER_H_

#include <stdint.h>

#include <optional>
#include <string>
#include <vector>

#include "base/containers/flat_set.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/util/display_util_export.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/hdr_static_metadata.h"

namespace display {

// This class parses a EDID (Extended Display Identification Data) binary blob
// passed on constructor, and provides access to the parsed information, plus
// a few utility postprocessings.
class DISPLAY_UTIL_EXPORT EdidParser {
 public:
  explicit EdidParser(std::vector<uint8_t> edid_blob, bool is_external = false);

  EdidParser(const EdidParser&) = delete;
  EdidParser& operator=(const EdidParser&) = delete;
  EdidParser(EdidParser&&);
  EdidParser& operator=(EdidParser&&);
  ~EdidParser();

  uint16_t manufacturer_id() const { return manufacturer_id_; }
  uint16_t product_id() const { return product_id_; }
  std::string block_zero_serial_number_hash() const {
    return block_zero_serial_number_hash_.value_or("");
  }
  std::string descriptor_block_serial_number_hash() const {
    return descriptor_block_serial_number_hash_.value_or("");
  }
  gfx::Size max_image_size() const {
    return max_image_size_.value_or(gfx::Size());
  }
  const std::string& display_name() const { return display_name_; }
  const gfx::Size& active_pixel_size() const { return active_pixel_size_; }
  int32_t week_of_manufacture() const {
    return week_of_manufacture_.value_or(0);
  }
  int32_t year_of_manufacture() const { return year_of_manufacture_; }
  bool has_overscan_flag() const { return overscan_flag_.has_value(); }
  bool overscan_flag() const { return overscan_flag_.value(); }
  double gamma() const { return gamma_; }
  int32_t bits_per_channel() const { return bits_per_channel_; }
  const SkColorSpacePrimaries& primaries() const { return primaries_; }
  using PrimaryMatrixPair =
      std::pair<gfx::ColorSpace::PrimaryID, gfx::ColorSpace::MatrixID>;
  const base::flat_set<PrimaryMatrixPair>& supported_color_primary_matrix_ids()
      const {
    return supported_color_primary_matrix_ids_;
  }
  const base::flat_set<gfx::ColorSpace::TransferID>&
  supported_color_transfer_ids() const {
    return supported_color_transfer_ids_;
  }
  const std::optional<gfx::HDRStaticMetadata>& hdr_static_metadata() const {
    return hdr_static_metadata_;
  }
  const std::optional<uint16_t>& vsync_rate_min() const {
    return vsync_rate_min_;
  }
  // Returns a 32-bit identifier for this display |manufacturer_id_| and
  // |product_id_|.
  uint32_t GetProductCode() const;

  // Generates a unique display id out of a mix of |manufacturer_id_|, hashed
  // |display_name_| if available, and |output_index|.
  // Here, uniqueness is heavily based on the connector's index to which the
  // display is attached to.
  int64_t GetIndexBasedDisplayId(uint8_t output_index) const;

  // Generates a unique display ID out of a mix of |manufacturer_id_|,
  // |product_id_|, |display_name_|, |week_of_manufacture_|,
  // |year_of_manufacture_|, |max_image_size_|,
  // |block_zero_serial_number_hash_|, and
  // |descriptor_block_serial_number_hash_|. Note that a hash will be produced
  // regardless of whether or not some (or all) of the fields are
  // missing/empty/default.
  // Here, uniqueness is solely based on a display's EDID and is not guaranteed
  // due to known EDIDs' completeness and correctness issues.
  int64_t GetEdidBasedDisplayId() const;

  // Bitmask of audio formats supported by the display.
  enum : uint32_t {
    kAudioBitstreamPcmLinear = 1u << 0,  // PCM is 'raw' amplitude samples.
    kAudioBitstreamDts = 1u << 1,        // Compressed DTS bitstream.
    kAudioBitstreamDtsHd = 1u << 2,      // Compressed DTS-HD bitstream.
  };
  uint32_t audio_formats() const { return audio_formats_; }

  // Splits the |product_code| (as returned by GetDisplayId()) into its
  // constituents |manufacturer_id| and |product_id|.
  static void SplitProductCodeInManufacturerIdAndProductId(
      int64_t product_code,
      uint16_t* manufacturer_id,
      uint16_t* product_id);
  // Extracts the three letter Manufacturer ID out of |manufacturer_id|.
  static std::string ManufacturerIdToString(uint16_t manufacturer_id);
  // Extracts the 2 Byte Product ID as hex out of |product_id|.
  static std::string ProductIdToString(uint16_t product_id);

  bool is_external_display() const { return is_external_display_; }

  // Returns true if the display is a tiled display and the tile (which all have
  // their own EDID) specified that its content will stretch to fit the entire
  // display across all tiles if the tile is the only tile being transmitted.
  // Returns false if the display is not tiled, if EDID does not have a
  // DisplayID tiled display block, or specifies a different behavior (e.g.
  // clone).
  bool TileCanScaleToFit() const;

  const std::vector<uint8_t>& edid_blob() const { return edid_blob_; }

 private:
  // Parses |edid_blob|, filling up as many as possible fields below.
  void ParseEdid(const std::vector<uint8_t>& edid);

  // We collect optional fields UMAs for external external displays only.
  void ReportEdidOptionalsForExternalDisplay() const;

  // DisplayID in this context refers to the VESA standard for display metadata,
  // not the identifier used throughout ash/ozone.
  void ParseDisplayIdExtension(const std::vector<uint8_t>& edid,
                               size_t extension_offset);

  // Parses Tiled Display Topology data blocks for DisplayID v1.3 and v2.0.
  void ParseTiledDisplayBlock(const std::vector<uint8_t>& edid,
                              size_t block_offset);

  std::vector<uint8_t> edid_blob_;

  // Whether or not this EDID belongs to an external display.
  bool is_external_display_;

  uint16_t manufacturer_id_;
  uint16_t product_id_;
  std::optional<std::string> block_zero_serial_number_hash_;
  std::optional<std::string> descriptor_block_serial_number_hash_;
  std::optional<gfx::Size> max_image_size_;
  std::string display_name_;
  // Active pixel size from the first detailed timing descriptor in the EDID.
  gfx::Size active_pixel_size_;
  // When |week_of_manufacture_| == 0xFF, |year_of_manufacture_| is model year.
  std::optional<int32_t> week_of_manufacture_;
  int32_t year_of_manufacture_;
  std::optional<bool> overscan_flag_;
  double gamma_;
  int bits_per_channel_;
  SkColorSpacePrimaries primaries_;

  base::flat_set<PrimaryMatrixPair> supported_color_primary_matrix_ids_;
  base::flat_set<gfx::ColorSpace::TransferID> supported_color_transfer_ids_;
  std::optional<gfx::HDRStaticMetadata> hdr_static_metadata_;
  std::optional<uint16_t> vsync_rate_min_;

  uint32_t audio_formats_;

  bool tile_can_scale_to_fit_ = false;
};

}  // namespace display

#endif  // UI_DISPLAY_UTIL_EDID_PARSER_H_