Skip to content

Commit b16fb97

Browse files
committed
egl: support getting the device via platform_device
a neat EXT
1 parent f2b6ebb commit b16fb97

File tree

2 files changed

+81
-14
lines changed

2 files changed

+81
-14
lines changed

src/render/OpenGL.cpp

Lines changed: 79 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
101101

102102
attrs.push_back(EGL_NONE);
103103

104-
m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : nullptr, attrs.data());
104+
m_pEglDisplay = m_sProc.eglGetPlatformDisplayEXT(gbm ? EGL_PLATFORM_GBM_KHR : EGL_PLATFORM_DEVICE_EXT, gbm ? m_pGbmDevice : m_pEglDevice, attrs.data());
105105
if (m_pEglDisplay == EGL_NO_DISPLAY)
106106
RASSERT(false, "EGL: failed to create a platform display");
107107

@@ -158,6 +158,60 @@ void CHyprOpenGLImpl::initEGL(bool gbm) {
158158
eglMakeCurrent(m_pEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_pEglContext);
159159
}
160160

161+
static bool drmDeviceHasName(const drmDevice* device, const std::string& name) {
162+
for (size_t i = 0; i < DRM_NODE_MAX; i++) {
163+
if (!(device->available_nodes & (1 << i)))
164+
continue;
165+
166+
if (device->nodes[i] == name)
167+
return true;
168+
}
169+
return false;
170+
}
171+
172+
EGLDeviceEXT CHyprOpenGLImpl::eglDeviceFromDRMFD(int drmFD) {
173+
EGLint nDevices = 0;
174+
if (!m_sProc.eglQueryDevicesEXT(0, nullptr, &nDevices)) {
175+
Debug::log(ERR, "eglDeviceFromDRMFD: eglQueryDevicesEXT failed");
176+
return EGL_NO_DEVICE_EXT;
177+
}
178+
179+
if (nDevices <= 0) {
180+
Debug::log(ERR, "eglDeviceFromDRMFD: no devices");
181+
return EGL_NO_DEVICE_EXT;
182+
}
183+
184+
std::vector<EGLDeviceEXT> devices;
185+
devices.resize(nDevices);
186+
187+
if (!m_sProc.eglQueryDevicesEXT(nDevices, devices.data(), &nDevices)) {
188+
Debug::log(ERR, "eglDeviceFromDRMFD: eglQueryDevicesEXT failed (2)");
189+
return EGL_NO_DEVICE_EXT;
190+
}
191+
192+
drmDevice* drmDev = nullptr;
193+
if (int ret = drmGetDevice(drmFD, &drmDev); ret < 0) {
194+
Debug::log(ERR, "eglDeviceFromDRMFD: drmGetDevice failed");
195+
return EGL_NO_DEVICE_EXT;
196+
}
197+
198+
for (auto& d : devices) {
199+
auto devName = m_sProc.eglQueryDeviceStringEXT(d, EGL_DRM_DEVICE_FILE_EXT);
200+
if (!devName)
201+
continue;
202+
203+
if (drmDeviceHasName(drmDev, devName)) {
204+
Debug::log(LOG, "eglDeviceFromDRMFD: Using device {}", devName);
205+
drmFreeDevice(&drmDev);
206+
return d;
207+
}
208+
}
209+
210+
drmFreeDevice(&drmDev);
211+
Debug::log(LOG, "eglDeviceFromDRMFD: No drm devices found");
212+
return EGL_NO_DEVICE_EXT;
213+
}
214+
161215
CHyprOpenGLImpl::CHyprOpenGLImpl() {
162216
const std::string EGLEXTENSIONS = (const char*)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
163217

@@ -202,22 +256,33 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
202256

203257
RASSERT(eglBindAPI(EGL_OPENGL_ES_API) != EGL_FALSE, "Couldn't bind to EGL's opengl ES API. This means your gpu driver f'd up. This is not a hyprland issue.");
204258

205-
// if (m_sProc.eglQueryDevicesEXT) {
206-
// // TODO:
207-
// }
259+
bool success = false;
260+
if (EGLEXTENSIONS.contains("EXT_platform_device") || !m_sProc.eglQueryDevicesEXT || !m_sProc.eglQueryDeviceStringEXT) {
261+
m_pEglDevice = eglDeviceFromDRMFD(m_iDRMFD);
208262

209-
if (EGLEXTENSIONS.contains("KHR_platform_gbm")) {
210-
m_iGBMFD = openRenderNode(m_iDRMFD);
211-
if (m_iGBMFD < 0)
212-
RASSERT(false, "Couldn't open a gbm fd");
263+
if (m_pEglDevice != EGL_NO_DEVICE_EXT) {
264+
success = true;
265+
initEGL(false);
266+
}
267+
}
213268

214-
m_pGbmDevice = gbm_create_device(m_iGBMFD);
215-
if (!m_pGbmDevice)
216-
RASSERT(false, "Couldn't open a gbm device");
269+
if (!success) {
270+
Debug::log(WARN, "EGL: EXT_platform_device or EGL_EXT_device_query not supported, using gbm");
271+
if (EGLEXTENSIONS.contains("KHR_platform_gbm")) {
272+
success = true;
273+
m_iGBMFD = openRenderNode(m_iDRMFD);
274+
if (m_iGBMFD < 0)
275+
RASSERT(false, "Couldn't open a gbm fd");
217276

218-
initEGL(true);
219-
} else
220-
RASSERT(false, "EGL does not support KHR_platform_gbm, this is an issue with your gpu driver.");
277+
m_pGbmDevice = gbm_create_device(m_iGBMFD);
278+
if (!m_pGbmDevice)
279+
RASSERT(false, "Couldn't open a gbm device");
280+
281+
initEGL(true);
282+
}
283+
}
284+
285+
RASSERT(success, "EGL does not support KHR_platform_gbm or EXT_platform_device, this is an issue with your gpu driver.");
221286

222287
auto* const EXTENSIONS = (const char*)glGetString(GL_EXTENSIONS);
223288
RASSERT(EXTENSIONS, "Couldn't retrieve openGL extensions!");

src/render/OpenGL.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class CHyprOpenGLImpl {
216216
gbm_device* m_pGbmDevice = nullptr;
217217
EGLContext m_pEglContext = nullptr;
218218
EGLDisplay m_pEglDisplay = nullptr;
219+
EGLDeviceEXT m_pEglDevice = nullptr;
219220

220221
bool m_bReloadScreenShader = true; // at launch it can be set
221222

@@ -280,6 +281,7 @@ class CHyprOpenGLImpl {
280281
void initShaders();
281282
void initDRMFormats();
282283
void initEGL(bool gbm);
284+
EGLDeviceEXT eglDeviceFromDRMFD(int drmFD);
283285

284286
//
285287
std::optional<std::vector<uint64_t>> getModsForFormat(EGLint format);

0 commit comments

Comments
 (0)