El 10/7/25 a las 12:36, Pierre Jasmin escribió:
> windows, mac and linux
>
As HDR is too new, you will probably have to delve into each platform's
API.
Regarding linux, not sure if there will be a consensus across
compositors or Wayland itself. Manolo, who is our FLTK's Wayland guy
may have some more info. For now, the recommended approach is to parse
the monitor's EDID information directly and reverse engineer it. You
can check the macOS info that does the same, albeit not sure if the
monitors will be compatible.
WARNING! Untested Windows code:
bool is_hdr_display_active()
{
IDXGIFactory6* factory = nullptr;
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
IDXGIAdapter1* adapter = nullptr;
for (UINT i = 0;
factory->EnumAdapters1(i, &adapter) !=
DXGI_ERROR_NOT_FOUND; ++i)
{
IDXGIOutput* output = nullptr;
if (SUCCEEDED(adapter->EnumOutputs(0, &output)))
{
IDXGIOutput6* output6 = nullptr;
if
(SUCCEEDED(output->QueryInterface(IID_PPV_ARGS(&output6))))
{
DXGI_OUTPUT_DESC1 desc;
output6->GetDesc1(&desc);
// Check for HDR support
if (desc.ColorSpace ==
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 ||
desc.ColorSpace ==
DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709)
{
std::cout << "HDR is active on display.\n";
output6->Release();
output->Release();
adapter->Release();
factory->Release();
return true;
}
output6->Release();
}
output->Release();
}
adapter->Release();
}
factory->Release();
return false;
}
macOS (semi-tested code):
#import <Foundation/Foundation.h>
#import <IOKit/graphics/IOGraphicsLib.h>
#import <IOKit/IOKitLib.h>
#import <CoreGraphics/CoreGraphics.h>
#import <iostream>
#import <vector>
#import <string>
#import <cstring>
#import <iostream>
// Parse EDID to detect HDR static metadata support
bool parseEDIDForHDR(const uint8_t* edid, size_t length) {
if (length < 128) return false;
uint8_t numExtensions = edid[126];
const uint8_t* ext = edid + 128;
for (int i = 0; i < numExtensions && (ext + 128 <= edid + length);
++i) {
if (ext[0] == 0x02 && ext[1] == 0x03) { // CTA-861 Extension Block
uint8_t dtdStart = ext[2];
if (dtdStart == 0 || dtdStart > 127) dtdStart = 127;
for (int j = 4; j < dtdStart - 4;) {
uint8_t tag = (ext[j] & 0xE0) >> 5;
uint8_t len = ext[j] & 0x1F;
if (tag == 0x07 && ext[j + 1] == 0x06) {
std::cout << "→ HDR static metadata block found in
EDID\n";
return true;
}
j += len + 1;
}
}
ext += 128;
}
return false;
}
bool displaySupportsHDR(CGDirectDisplayID cgDisplayID) {
io_iterator_t iter;
io_service_t service = 0;
CFMutableDictionaryRef match = IOServiceMatching("IODisplayConnect");
if (IOServiceGetMatchingServices(kIOMasterPortDefault, match,
&iter) != KERN_SUCCESS)
return false;
while ((service = IOIteratorNext(iter))) {
CFDictionaryRef info = IODisplayCreateInfoDictionary(service,
kIODisplayOnlyPreferredName);
if (!info) {
IOObjectRelease(service);
continue;
}
CFNumberRef vendorRef = (CFNumberRef)CFDictionaryGetValue(info,
CFSTR(kDisplayVendorID));
CFNumberRef productRef =
(CFNumberRef)CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
uint32_t vendor = 0, product = 0;
if (vendorRef) CFNumberGetValue(vendorRef, kCFNumberIntType,
&vendor);
if (productRef) CFNumberGetValue(productRef, kCFNumberIntType,
&product);
CFRelease(info);
// Match against CoreGraphics display info
uint32_t cgVendor = CGDisplayVendorNumber(cgDisplayID);
uint32_t cgProduct = CGDisplayModelNumber(cgDisplayID);
if (vendor == cgVendor && product == cgProduct) {
CFDataRef edid =
(CFDataRef)IORegistryEntryCreateCFProperty(service,
CFSTR("IODisplayEDID"), kCFAllocatorDefault, 0);
bool result = false;
if (edid) {
const UInt8* bytes = CFDataGetBytePtr(edid);
CFIndex length = CFDataGetLength(edid);
result = parseEDIDForHDR(bytes, length);
CFRelease(edid);
}
IOObjectRelease(service);
IOObjectRelease(iter);
return result;
}
IOObjectRelease(service);
}
IOObjectRelease(iter);
return false;
}
--
ggar...@gmail.com