2016-04-27 11 views
3

Apple недавно включила поддержку 30-битного цвета в OS X. Они разместили сообщение sample code, в котором показано, как включить это. Тем не менее, они не показывают пример того, как вы можете обнаружить, когда приложение работает на дисплее, поддерживающем 30-битный цвет.Обнаружение, если дисплей поддерживает 30-битный цвет

Мы хотели бы иметь возможность обнаруживать, когда дисплей поддерживает 30-битный цвет и разрешает только 30-битный цвет для дисплеев, которые поддерживают его, и возвращают к 24-битовому цвету в противном случае.

Кто-нибудь знает, как это сделать?

До сих пор я пытался использовать API-интерфейсы CGDisplay (CGDisplayCopyDisplayMode и CGDisplayModeCopyPixelEncoding), чтобы запросить кодировку пикселя дисплея. Но они, похоже, всегда возвращают 24-битные кодировки, а CGDisplayModeCopyPixelEncoding устарел в Mac OS X 10.11. Я также пытался использовать NSScreen’s свойство «depth», но это также возвращает 24 бит на пиксель.

Встроенное системное информационное приложение, очевидно, может получить эту информацию, я просто не могу понять, как они это делают. Любые намеки?

ответ

1

As macOS 10.12 У Apple есть несколько новых API-интерфейсов, которые позволяют вам определить, способен ли дисплей иметь широкий цвет гаммы (т. Е. Глубокий цвет). Есть несколько способов сделать это:

  1. Используйте NSScreen в - (BOOL)canRepresentDisplayGamut:(NSDisplayGamut)displayGamut

    NSArray<NSScreen *> * screens = [NSScreen screens]; 
    BOOL hasWideGamutScreen = NO; 
    
    for (NSScreen * screen in screens) 
    { 
        if ([screen canRepresentDisplayGamut:NSDisplayGamutP3]) 
        { 
         hasWideGamutScreen = YES; 
         break; 
        } 
    } 
    
  2. CGColorSpaceIsWideGamutRGB(...) Использование:

    hasWideGamutScreen = CGColorSpaceIsWideGamutRGB(screen.colorSpace.CGColorSpace); 
    
  3. NSWindow также - (BOOL)canRepresentDisplayGamut:(NSDisplayGamut)displayGamut.

Я не знаю, что вы гарантированно на 30-битным дисплеем, способным, когда дисплей считается «широкий диапазон RGB» или способный NSDisplayGamutP3, но это, кажется официальным способом Яблока определяя, может ли дисплей иметь широкий цвет гаммы.

0

Существуют различные плохие варианты.

Прежде всего, если вы зарегистрируете режим отображения (т. Е. Отбрасываете до id и переходите на NSLog(@"%@", ...)), вы обнаружите, что существует реальное кодирование пикселей. Это интересно, но вы действительно не хотите разбирать это описание.

Если вы передадите (__bridge CFDictionaryRef)@{ (__bridge NSString*)kCGDisplayShowDuplicateLowResolutionModes: @YES } в качестве параметра параметров CGDisplayCopyAllDisplayModes(), вы обнаружите, что получаете кучу дополнительных режимов отображения. Этот ключ документируется в заголовках, но не в справочной документации. Для дисплея Retina некоторые дополнительные режимы представляют собой 2x-масштабированные копии немасштабированных режимов отображения. Другие - 24-разрядные аналоги 30-битных маскарадирующих-24-битных режимов. Они идентичны во всех отношениях, которые вы можете запросить через API, но журнал показывает разницу. (Кстати, попытка переключиться на один из этих режимов завершится с ошибкой.)

Я думаю, но вам нужно будет убедиться, что вы не получите эти пары кажущихся одинаковыми режимов, кроме 30- бит-цветной дисплей.

Возможно, вы сможете получить информацию от IOKit. Вам нужно будет использовать устаревшую функцию CGDisplayIOServicePort(), чтобы получить служебный порт объекта IOFramebuffer, представляющего пару GPU-дисплеев. Затем вы можете использовать IORegistryEntrySearchCFProperty() для поиска иерархии сдерживания на плоскости обслуживания, чтобы найти объект, обладающий свойством «display-bpc» или «display-pixel-component-bits» и получить его значение. По крайней мере, есть такой объект и свойства на нескольких системах, которые я могу проверить, хотя оба они используют графические процессоры AMD, а свойство находится на объекте, специфичном для AMD, поэтому оно может быть ненадежным.

Наконец, вы можете запустить подпроцесс для запуска system_profiler -xml SPDisplaysDataType и использовать API-интерфейс сериализации свойств для создания объекта списка свойств из полученного XML. Затем вы можете найти информацию там. Вы найдете соответствующий дисплей, сопоставив _spdisplays_display-vendor-id с CGDisplayVendorNumber(), _spdisplays_display-product-id с CGDisplayModelNumber() и _spdisplays_display-serial-number с CGDisplaySerialNumber(). Затем глубина находится под ключом spdisplays_depth, где значение CGSThirtyBitColor означает 30-битный цвет.

Вы также должны подать отчет об ошибке с Apple, требуя разумного способа сделать это.

+1

Вау, эти ** являются ** довольно плохими вариантами. Следуя подсказке «NSLog», я обнаружил, что структура 'CGDisplayModeRef' имеет указатель на словарь (' CFDictionary'), который составляет 16 байтов из базы структуры в памяти. Затем вы можете запросить этот словарь для ключей '' PixelEncoding "или' "BitsPerSample" ". Однако это довольно ужасное решение, так как я не хочу полагаться на частную реализацию структуры CGDisplayModeRef, поскольку это может измениться в любом будущем обновлении ОС. Я действительно не хочу использовать 'CGDisplayIOServicePort()' либо, так как он устарел. Действительно плохие варианты ... – Cutterpillow

0

То, что сработало для меня пропускание depthLimit свойства моей NSWindow в и проверках того, что возвращаемое значение больше 24. Протест: У меня только два Маков, чтобы проверить на, один из 2012, а другие с 2017 года, и они Оба они бегут в Сьерра.