From 8d0a0c43c1416e8540b0adf527be2ec5c69cccff Mon Sep 17 00:00:00 2001 From: Lucas Berthou Date: Tue, 27 Aug 2024 14:32:31 +0000 Subject: SF: parsing Detailed Timing Descriptor in the framework The first DTD in an edid is the preferred timing which allows to get a more precise and more often correct physical size for a display. This can be used to estimate or correct the dpi in case the edid reports the wrong size and hwc is not providing the right value. See edid spec: https://glenwing.github.io/docs/VESA-EEDID-A2.pdf Flag: com.android.graphics.surfaceflinger.flags.correct_dpi_with_display_size Bug: 361413340 Test: DisplayIdentification_test Test: HWComposerTest Test: manual - see bug and doc Change-Id: I0bb85dcf8039f923f1ac892c4a1d6bda771dbf4f --- libs/ui/DisplayIdentification.cpp | 69 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 11 deletions(-) (limited to 'libs/ui/DisplayIdentification.cpp') diff --git a/libs/ui/DisplayIdentification.cpp b/libs/ui/DisplayIdentification.cpp index e5af7406ed..8b13d78840 100644 --- a/libs/ui/DisplayIdentification.cpp +++ b/libs/ui/DisplayIdentification.cpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace android { namespace { @@ -46,6 +47,10 @@ std::optional getEdidDescriptorType(const byte_view& view) { return view[3]; } +bool isDetailedTimingDescriptor(const byte_view& view) { + return view[0] != 0 && view[1] != 0; +} + std::string_view parseEdidText(const byte_view& view) { std::string_view text(reinterpret_cast(view.data()), view.size()); text = text.substr(0, text.find('\n')); @@ -219,6 +224,8 @@ std::optional parseEdid(const DisplayIdentificationData& edid) { std::string_view displayName; std::string_view serialNumber; std::string_view asciiText; + ui::Size preferredDTDPixelSize; + ui::Size preferredDTDPhysicalSize; constexpr size_t kDescriptorCount = 4; constexpr size_t kDescriptorLength = 18; @@ -243,6 +250,35 @@ std::optional parseEdid(const DisplayIdentificationData& edid) { serialNumber = parseEdidText(descriptor); break; } + } else if (isDetailedTimingDescriptor(view)) { + static constexpr size_t kHorizontalPhysicalLsbOffset = 12; + static constexpr size_t kHorizontalPhysicalMsbOffset = 14; + static constexpr size_t kVerticalPhysicalLsbOffset = 13; + static constexpr size_t kVerticalPhysicalMsbOffset = 14; + const uint32_t hSize = + static_cast(view[kHorizontalPhysicalLsbOffset] | + ((view[kHorizontalPhysicalMsbOffset] >> 4) << 8)); + const uint32_t vSize = + static_cast(view[kVerticalPhysicalLsbOffset] | + ((view[kVerticalPhysicalMsbOffset] & 0b1111) << 8)); + + static constexpr size_t kHorizontalPixelLsbOffset = 2; + static constexpr size_t kHorizontalPixelMsbOffset = 4; + static constexpr size_t kVerticalPixelLsbOffset = 5; + static constexpr size_t kVerticalPixelMsbOffset = 7; + + const uint8_t hLsb = view[kHorizontalPixelLsbOffset]; + const uint8_t hMsb = view[kHorizontalPixelMsbOffset]; + const int32_t hPixel = hLsb + ((hMsb & 0xF0) << 4); + + const uint8_t vLsb = view[kVerticalPixelLsbOffset]; + const uint8_t vMsb = view[kVerticalPixelMsbOffset]; + const int32_t vPixel = vLsb + ((vMsb & 0xF0) << 4); + + preferredDTDPixelSize.setWidth(hPixel); + preferredDTDPixelSize.setHeight(vPixel); + preferredDTDPhysicalSize.setWidth(hSize); + preferredDTDPhysicalSize.setHeight(vSize); } view = view.subspan(kDescriptorLength); @@ -297,14 +333,22 @@ std::optional parseEdid(const DisplayIdentificationData& edid) { } } - return Edid{.manufacturerId = manufacturerId, - .productId = productId, - .pnpId = *pnpId, - .modelHash = modelHash, - .displayName = displayName, - .manufactureOrModelYear = manufactureOrModelYear, - .manufactureWeek = manufactureWeek, - .cea861Block = cea861Block}; + DetailedTimingDescriptor preferredDetailedTimingDescriptor{ + .pixelSizeCount = preferredDTDPixelSize, + .physicalSizeInMm = preferredDTDPhysicalSize, + }; + + return Edid{ + .manufacturerId = manufacturerId, + .productId = productId, + .pnpId = *pnpId, + .modelHash = modelHash, + .displayName = displayName, + .manufactureOrModelYear = manufactureOrModelYear, + .manufactureWeek = manufactureWeek, + .cea861Block = cea861Block, + .preferredDetailedTimingDescriptor = preferredDetailedTimingDescriptor, + }; } std::optional getPnpId(uint16_t manufacturerId) { @@ -336,9 +380,12 @@ std::optional parseDisplayIdentificationData( } const auto displayId = PhysicalDisplayId::fromEdid(port, edid->manufacturerId, edid->modelHash); - return DisplayIdentificationInfo{.id = displayId, - .name = std::string(edid->displayName), - .deviceProductInfo = buildDeviceProductInfo(*edid)}; + return DisplayIdentificationInfo{ + .id = displayId, + .name = std::string(edid->displayName), + .deviceProductInfo = buildDeviceProductInfo(*edid), + .preferredDetailedTimingDescriptor = edid->preferredDetailedTimingDescriptor, + }; } PhysicalDisplayId getVirtualDisplayId(uint32_t id) { -- cgit v1.2.3-59-g8ed1b