PhycialDisplay (macOS): add support

This commit is contained in:
李通洲 2023-08-09 10:11:24 +08:00
parent bb0279bae1
commit 1d1ce83567
No known key found for this signature in database
GPG Key ID: 269AD4F5325A22A3
6 changed files with 137 additions and 32 deletions

View File

@ -541,7 +541,7 @@ elseif(APPLE)
src/detection/gamepad/gamepad_apple.c
src/detection/media/media_apple.m
src/detection/memory/memory_apple.c
src/detection/phycialdisplay/phycialdisplay_nosupport.c
src/detection/phycialdisplay/phycialdisplay_apple.c
src/detection/opengl/opengl_apple.c
src/detection/os/os_apple.m
src/detection/packages/packages_apple.c

View File

@ -1,20 +1,11 @@
#include "brightness.h"
#include "detection/displayserver/displayserver.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/ddcci.h"
#include "util/edidHelper.h"
#include <CoreGraphics/CoreGraphics.h>
extern int DisplayServicesGetBrightness(CGDirectDisplayID display, float *brightness) __attribute__((weak_import));
// DDC/CI
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import));
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import));
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import));
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import));
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
// Works for internal display
static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* result)
{
@ -23,12 +14,15 @@ static const char* detectWithDisplayServices(const FFDisplayServerResult* displa
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
float value;
if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess)
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN)
{
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = value * 100;
ffStrbufInitCopy(&brightness->name, &display->name);
float value;
if(DisplayServicesGetBrightness((CGDirectDisplayID) display->id, &value) == kCGErrorSuccess)
{
FFBrightnessResult* brightness = (FFBrightnessResult*) ffListAdd(result);
brightness->value = value * 100;
ffStrbufInitCopy(&brightness->name, &display->name);
}
}
}
@ -108,22 +102,11 @@ static const char* detectWithDdcci(FFlist* result)
return NULL;
}
static bool hasBuiltinDisplay(const FFDisplayServerResult* displayServer)
{
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN)
return true;
}
return false;
}
const char* ffDetectBrightness(FFlist* result)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
if (hasBuiltinDisplay(displayServer))
detectWithDisplayServices(displayServer, result);
detectWithDisplayServices(displayServer, result);
if (instance.config.allowSlowOperations && displayServer->displays.length > result->length)
detectWithDdcci(result);

View File

@ -0,0 +1,107 @@
#include "phycialdisplay.h"
#include "detection/displayserver/displayserver.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/ddcci.h"
#include "util/edidHelper.h"
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
static const char* detectWithDisplayServices(const FFDisplayServerResult* displayServer, FFlist* results)
{
if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available";
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
{
if (display->type == FF_DISPLAY_TYPE_BUILTIN || display->type == FF_DISPLAY_TYPE_UNKNOWN)
{
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
if(displayInfo)
{
int width, height;
if (ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelWidth"), &width) ||
ffCfDictGetInt(displayInfo, CFSTR("kCGDisplayPixelHeight"), &height) ||
width <= 0 || height <= 0)
continue;
FFPhycialDisplayResult* display = (FFPhycialDisplayResult*) ffListAdd(results);
display->width = (uint32_t) width;
display->height = (uint32_t) height;
ffStrbufInit(&display->name);
CFDictionaryRef productNames;
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
ffCfDictGetString(productNames, CFSTR("en_US"), &display->name);
}
}
}
return NULL;
}
static const char* detectWithDdcci(FFlist* results)
{
if (!IOAVServiceCreate || !IOAVServiceReadI2C)
return "IOAVService is not available";
CFMutableDictionaryRef matchDict = IOServiceMatching("DCPAVServiceProxy");
if (matchDict == NULL)
return "IOServiceMatching(\"DCPAVServiceProxy\") failed";
io_iterator_t iterator;
if(IOServiceGetMatchingServices(MACH_PORT_NULL, matchDict, &iterator) != kIOReturnSuccess)
return "IOServiceGetMatchingServices() failed";
FF_STRBUF_AUTO_DESTROY location = ffStrbufCreate();
io_registry_entry_t registryEntry;
while((registryEntry = IOIteratorNext(iterator)) != 0)
{
CFMutableDictionaryRef properties;
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
{
IOObjectRelease(registryEntry);
continue;
}
ffStrbufClear(&location);
if(ffCfDictGetString(properties, CFSTR("Location"), &location) || ffStrbufEqualS(&location, "Embedded"))
{
// Builtin display should be handled by DisplayServices
IOObjectRelease(registryEntry);
continue;
}
FF_CFTYPE_AUTO_RELEASE IOAVServiceRef service = IOAVServiceCreateWithService(kCFAllocatorDefault, (io_service_t) registryEntry);
IOObjectRelease(registryEntry);
if (!service) continue;
FF_CFTYPE_AUTO_RELEASE CFDataRef edid = NULL;
if (IOAVServiceCopyEDID(service, &edid) != KERN_SUCCESS )
continue;
if (CFDataGetLength(edid) < 128)
continue;
uint32_t width, height;
ffEdidGetPhycialDisplay(CFDataGetBytePtr(edid), &width, &height);
if (width == 0 || height == 0) continue;
FFPhycialDisplayResult* display = (FFPhycialDisplayResult*) ffListAdd(results);
display->width = width;
display->height = height;
ffStrbufInit(&display->name);
ffEdidGetName(CFDataGetBytePtr(edid), &display->name);
}
return NULL;
}
const char* ffDetectPhycialDisplay(FFlist* results)
{
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
detectWithDisplayServices(displayServer, results);
if (displayServer->displays.length > results->length)
detectWithDdcci(results);
return NULL;
}

15
src/util/apple/ddcci.h Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#ifndef FASTFETCH_INCLUDED_util_apple_ddcci_h
#include <CoreGraphics/CoreGraphics.h>
// DDC/CI
typedef CFTypeRef IOAVServiceRef;
extern IOAVServiceRef IOAVServiceCreate(CFAllocatorRef allocator) __attribute__((weak_import));
extern IOAVServiceRef IOAVServiceCreateWithService(CFAllocatorRef allocator, io_service_t service) __attribute__((weak_import));
extern IOReturn IOAVServiceCopyEDID(IOAVServiceRef service, CFDataRef* x2) __attribute__((weak_import));
extern IOReturn IOAVServiceReadI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize) __attribute__((weak_import));
extern IOReturn IOAVServiceWriteI2C(IOAVServiceRef service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize) __attribute__((weak_import));
#endif

View File

@ -1,13 +1,13 @@
#include "edidHelper.h"
void ffEdidGetPhycialDisplay(uint8_t edid[128], uint32_t* width, uint32_t* height)
void ffEdidGetPhycialDisplay(const uint8_t edid[128], uint32_t* width, uint32_t* height)
{
const int dtd = 54;
*width = (((uint32_t) edid[dtd + 4] >> 4) << 8) | edid[dtd + 2];
*height = (((uint32_t) edid[dtd + 7] >> 4) << 8) | edid[dtd + 5];
}
void ffEdidGetName(uint8_t edid[128], FFstrbuf* name)
void ffEdidGetName(const uint8_t edid[128], FFstrbuf* name)
{
// https://github.com/jinksong/read_edid/blob/master/parse-edid/parse-edid.c
for (uint32_t i = 0x36; i < 0x7E; i += 0x12)

View File

@ -6,7 +6,7 @@
#include <stdint.h>
#include "util/FFstrbuf.h"
void ffEdidGetPhycialDisplay(uint8_t edid[128], uint32_t* width, uint32_t* height);
void ffEdidGetName(uint8_t edid[128], FFstrbuf* name);
void ffEdidGetPhycialDisplay(const uint8_t edid[128], uint32_t* width, uint32_t* height);
void ffEdidGetName(const uint8_t edid[128], FFstrbuf* name);
#endif