DisplayServer (Linux): check if RANDR is running in Emulation mode

This commit is contained in:
Carter Li
2026-03-05 10:12:15 +08:00
parent e6db59fdde
commit b64d8a013d
2 changed files with 84 additions and 39 deletions
+39 -17
View File
@@ -78,6 +78,19 @@ static void* xcbGetProperty(XcbRandrData* data, xcb_window_t window, const char*
return replyValue;
}
static xcb_randr_get_output_property_reply_t* xcbRandrGetProperty(XcbRandrData* data, xcb_randr_output_t output, const char* name)
{
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen(name), name);
FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL);
if(requestAtomReply)
{
xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false);
return data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL);
}
return NULL;
}
static void xcbDetectWMfromEWMH(XcbRandrData* data, xcb_window_t rootWindow, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
@@ -121,28 +134,34 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
if(outputInfoReply == NULL)
return false;
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen("EDID"), "EDID");
FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL);
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* outputPropertyReply = NULL;
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* edidReply = xcbRandrGetProperty(data, output, "EDID");
uint8_t* edidData = NULL;
uint32_t edidLength = 0;
if(requestAtomReply)
if(edidReply)
{
xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false);
outputPropertyReply = data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL);
if(outputPropertyReply)
int len = data->ffxcb_randr_get_output_property_data_length(edidReply);
if(len >= 128)
{
int len = data->ffxcb_randr_get_output_property_data_length(outputPropertyReply);
if(len >= 128)
{
ffStrbufClear(name);
edidData = data->ffxcb_randr_get_output_property_data(outputPropertyReply);
ffEdidGetName(edidData, name);
edidLength = (uint32_t) len;
}
edidData = data->ffxcb_randr_get_output_property_data(edidReply);
edidLength = (uint32_t) len;
}
}
if(edidData)
{
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
uint8_t randrEmulation = 0;
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* randrEmulationReply = xcbRandrGetProperty(data, output, "RANDR Emulation");
if(randrEmulationReply)
{
int len = data->ffxcb_randr_get_output_property_data_length(randrEmulationReply);
if(len >= 1)
randrEmulation = data->ffxcb_randr_get_output_property_data(randrEmulationReply)[0];
}
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, outputInfoReply->crtc, XCB_CURRENT_TIME);
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
if(crtcInfoReply == NULL)
@@ -204,9 +223,12 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
0,
(uint32_t) outputInfoReply->mm_width,
(uint32_t) outputInfoReply->mm_height,
currentMode ? "xcb-randr-mode" : "xcb-randr-crtc"
randrEmulation
? (currentMode ? "xcb-randr-emu-mode" : "xcb-randr-emu-crtc")
: (currentMode ? "xcb-randr-mode" : "xcb-randr-crtc")
);
if (item && edidLength)
if (item && edidData && edidLength >= 128)
{
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
+45 -22
View File
@@ -48,6 +48,32 @@ static unsigned char* x11GetProperty(XrandrData* data, Display* display, Window
return result;
}
static uint8_t* xrandrGetProperty(XrandrData* data, RROutput output, const char* name, uint32_t* bufSize)
{
unsigned long size = 0;
uint8_t* result = NULL;
Atom atomEdid = data->ffXInternAtom(data->display, name, true);
if (atomEdid != None)
{
int actual_format = 0;
unsigned long bytes_after = 0;
Atom actual_type = None;
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &size, &bytes_after, &result) == Success)
{
if (size == 0)
data->ffXFree(result);
else
{
if (bufSize)
*bufSize = (uint32_t) size;
return result;
}
}
}
return NULL;
}
static void x11DetectWMFromEWMH(XrandrData* data, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0)
@@ -75,7 +101,7 @@ static void x11FetchServerVendor(XrandrData* data, FFDisplayServerResult* result
ffStrbufSetS(&result->wmProtocolName, serverVendor);
}
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor)
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor, bool randrEmulation)
{
//We do the check here, because we want the best fallback display if this call failed
if(screenResources == NULL)
@@ -131,7 +157,9 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
0,
(uint32_t) output->mm_width,
(uint32_t) output->mm_height,
currentMode ? "xlib-randr-mode" : "xlib-randr-crtc"
randrEmulation
? (currentMode ? "xlib-randr-emu-mode" : "xlib-randr-emu-crtc")
: (currentMode ? "xlib-randr-mode" : "xlib-randr-crtc")
);
if (item)
@@ -154,30 +182,25 @@ static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name
if(outputInfo == NULL)
return false;
uint8_t* edidData = NULL;
unsigned long edidLength = 0;
Atom atomEdid = data->ffXInternAtom(data->display, "EDID", true);
if (atomEdid != None)
{
int actual_format = 0;
unsigned long bytes_after = 0;
Atom actual_type = None;
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &edidLength, &bytes_after, &edidData) == Success)
{
if (edidLength >= 128)
{
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
else
edidLength = 0;
}
}
uint32_t edidLength = 0;
uint8_t* edidData = xrandrGetProperty(data, output, RR_PROPERTY_RANDR_EDID, &edidLength);
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, (uint32_t) edidLength, screenResources, bitDepth, scaleFactor);
if (edidLength >= 128)
{
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
else
edidLength = 0;
uint8_t* randrEmulation = xrandrGetProperty(data, output, "RANDR Emulation", NULL);
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, edidLength, screenResources, bitDepth, scaleFactor, randrEmulation ? !!randrEmulation[0] : false);
if (edidData)
data->ffXFree(edidData);
if (randrEmulation)
data->ffXFree(randrEmulation);
data->ffXRRFreeOutputInfo(outputInfo);
return res;