hw/modesetting: Fix up cursor size probing.

modesetting has a sort of broken concept of getting the cursor dimensions since 1f41320e1c, which causes issues on virtual machines and older AMD hardware. Our solution is to use SIZE_HINTS which is available in i915 since 2023 otherwise fallback to getting the cursor size provided by the driver, if a driver wants to have a more optimal cursor size, it is more than welcome to implement SIZE_HINTS in it's DRM interface.

Taken from my own fork of Xorg.

v2: Fix some bugs in the implemenation.
This commit is contained in:
notbabaisyou
2025-08-14 14:06:58 +02:00
committed by Enrico Weigelt
parent e7455f48a3
commit e6c980f08e
5 changed files with 245 additions and 108 deletions

View File

@@ -1228,17 +1228,6 @@ PreInit(ScrnInfoPtr pScrn, int flags)
ms->drmmode.sw_cursor = TRUE;
}
ms->max_cursor_width = 64;
ms->max_cursor_height = 64;
ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value);
if (!ret) {
ms->max_cursor_width = value;
}
ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value);
if (!ret) {
ms->max_cursor_height = value;
}
try_enable_glamor(pScrn);
if (!ms->drmmode.glamor) {
@@ -1964,9 +1953,14 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
PointPriv->spriteFuncs = &drmmode_sprite_funcs;
}
/* Get the maximum cursor size. */
drmmode_cursor_dim_rec cursor_dim = { 0 };
if (!drmmode_get_largest_cursor(pScrn, &cursor_dim))
return FALSE;
/* Need to extend HWcursor support to handle mask interleave */
if (!ms->drmmode.sw_cursor)
xf86_cursors_init(pScreen, ms->max_cursor_width, ms->max_cursor_height,
xf86_cursors_init(pScreen, cursor_dim.width, cursor_dim.height,
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
HARDWARE_CURSOR_UPDATE_UNHIDDEN |
HARDWARE_CURSOR_ARGB);

View File

@@ -131,9 +131,6 @@ typedef struct _modesettingRec {
DamagePtr damage;
Bool dirty_enabled;
uint32_t min_cursor_width, min_cursor_height;
uint32_t max_cursor_width, max_cursor_height;
Bool has_queue_sequence;
Bool tried_queue_sequence;

View File

@@ -1795,7 +1795,7 @@ drmmode_set_cursor(xf86CrtcPtr crtc, int width, int height)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
uint32_t handle = drmmode_crtc->cursor.bo->handle;
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
int ret = -EINVAL;
@@ -1835,6 +1835,18 @@ drmmode_set_cursor(xf86CrtcPtr crtc, int width, int height)
static void drmmode_hide_cursor(xf86CrtcPtr crtc);
static inline int
get_maximum_cursor_width(drmmode_cursor_rec cursor)
{
return cursor.dimensions[cursor.num_dimensions - 1].width;
}
static inline int
get_maximum_cursor_height(drmmode_cursor_rec cursor)
{
return cursor.dimensions[cursor.num_dimensions - 1].height;
}
/*
* The load_cursor_argb_check driver hook.
*
@@ -1845,45 +1857,49 @@ static void drmmode_hide_cursor(xf86CrtcPtr crtc);
static Bool
drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 *image)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
CursorPtr cursor = xf86CurrentCursor(crtc->scrn->pScreen);
drmmode_cursor_rec drmmode_cursor = drmmode_crtc->cursor;
int width, height, x, y, i;
int max_width, max_height;
uint32_t *ptr;
/* cursor should be mapped already */
ptr = (uint32_t *) (drmmode_crtc->cursor_bo->ptr);
ptr = (uint32_t *) (drmmode_cursor.bo->ptr);
/* FIXME deal with rotation */
if (crtc->rotation == RR_Rotate_0) {
for (width = ms->min_cursor_width; width < cursor->bits->width; )
width *= 2;
for (height = ms->min_cursor_height; height < cursor->bits->height; )
height *= 2;
/* We need to know what our limit is for HW cursors. */
max_width = get_maximum_cursor_width(drmmode_cursor);
max_height = get_maximum_cursor_height(drmmode_cursor);
/* assume only square works for now */
width = height = max(width, height);
/* Find the most compatiable size. */
for (i = 0; i < drmmode_cursor.num_dimensions; i++)
{
drmmode_cursor_dim_rec dimensions = drmmode_cursor.dimensions[i];
/* if the max limits aren't square+POT we may have gone a bit over */
width = min(width, ms->max_cursor_width);
height = min(height, ms->max_cursor_height);
} else {
width = ms->max_cursor_width;
height = ms->max_cursor_height;
if (dimensions.width > cursor->bits->width &&
dimensions.height > cursor->bits->height)
break;
}
/* Get the resolution of the cursor. */
width = drmmode_cursor.dimensions[i].width;
height = drmmode_cursor.dimensions[i].height;
/* Copy the cursor image over. */
i = 0;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
ptr[i++] = image[y * ms->max_cursor_width + x]; // cpu_to_le32(image[i]);
ptr[i++] = image[y * max_width + x];
}
/* clear the remainder for good measure */
for (; i < ms->max_cursor_width * ms->max_cursor_height; i++)
/* Clear the remainder for good measure. */
for (; i < max_width * max_height; i++)
ptr[i++] = 0;
if (drmmode_crtc->cursor_up)
return drmmode_set_cursor(crtc, width, height);
return TRUE;
else
return TRUE;
}
static void
@@ -2262,6 +2278,7 @@ drmmode_crtc_destroy(xf86CrtcPtr crtc)
return;
drmmode_prop_info_free(drmmode_crtc->props_plane, DRMMODE_PLANE__COUNT);
free(drmmode_crtc->cursor.dimensions);
xorg_list_for_each_entry_safe(iterator, next, &drmmode_crtc->mode_list, entry) {
drm_mode_destroy(crtc, iterator);
}
@@ -2372,6 +2389,152 @@ populate_format_modifiers(xf86CrtcPtr crtc, const drmModePlane *kplane,
return TRUE;
}
#ifdef LIBDRM_PLANE_SIZE_HINTS
static void
populate_cursor_sizes(drmmode_ptr drmmode, drmmode_crtc_private_ptr drmmode_crtc, int size_hints_blob)
{
drmModePropertyBlobRes *blob;
if (!drmmode_crtc)
return;
if (!size_hints_blob)
return;
blob = drmModeGetPropertyBlob(drmmode->fd, size_hints_blob);
if (!blob)
return;
if (!blob->length)
goto fail;
const struct drm_plane_size_hint *size_hints = blob->data;
size_t size_hints_len = blob->length / sizeof(size_hints[0]);
if (!size_hints_len)
goto fail;
drmmode_crtc->cursor.num_dimensions = size_hints_len;
drmmode_crtc->cursor.dimensions = xnfrealloc(drmmode_crtc->cursor.dimensions, size_hints_len * sizeof(drmmode_cursor_dim_rec));
for (int idx = 0; idx < size_hints_len; idx++)
{
struct drm_plane_size_hint size_hint = size_hints[idx];
drmmode_crtc->cursor.dimensions[idx].width = size_hint.width;
drmmode_crtc->cursor.dimensions[idx].height = size_hint.height;
}
fail:
drmModeFreePropertyBlob(blob);
}
static void
drmmode_crtc_probe_size_hint(xf86CrtcPtr crtc, int num)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
drmModePlaneRes *kplane_res;
drmModeObjectProperties *props;
drmModePlane *kplane = NULL;
uint32_t i, type;
static drmmode_prop_enum_info_rec plane_type_enums[] = {
[DRMMODE_PLANE_TYPE_PRIMARY] = {
.name = "Primary",
},
[DRMMODE_PLANE_TYPE_OVERLAY] = {
.name = "Overlay",
},
[DRMMODE_PLANE_TYPE_CURSOR] = {
.name = "Cursor",
},
};
static const drmmode_prop_info_rec plane_props[] = {
[DRMMODE_PLANE_TYPE] = {
.name = "type",
.enum_values = plane_type_enums,
.num_enum_values = DRMMODE_PLANE_TYPE__COUNT,
},
[DRMMODE_PLANE_FB_ID] = { .name = "FB_ID", },
[DRMMODE_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
[DRMMODE_PLANE_IN_FORMATS] = { .name = "IN_FORMATS", },
[DRMMODE_PLANE_SRC_X] = { .name = "SRC_X", },
[DRMMODE_PLANE_SRC_Y] = { .name = "SRC_Y", },
[DRMMODE_PLANE_SRC_W] = { .name = "SRC_W", },
[DRMMODE_PLANE_SRC_H] = { .name = "SRC_H", },
[DRMMODE_PLANE_CRTC_X] = { .name = "CRTC_X", },
[DRMMODE_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
[DRMMODE_PLANE_CRTC_W] = { .name = "CRTC_W", },
[DRMMODE_PLANE_CRTC_H] = { .name = "CRTC_H", },
[DRMMODE_PLANE_SIZE_HINTS] = { .name = "SIZE_HINTS" }
};
drmmode_prop_info_rec tmp_props[DRMMODE_PLANE__COUNT];
if (!drmmode_prop_info_copy(tmp_props, plane_props, DRMMODE_PLANE__COUNT, 0)) {
xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
"failed to copy plane property info\n");
drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
return;
}
kplane_res = drmModeGetPlaneResources(drmmode->fd);
if (!kplane_res) {
xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
"failed to get plane resources: %s\n", strerror(errno));
drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
return;
}
for (i = 0; i < kplane_res->count_planes; i++) {
int plane_id;
kplane = drmModeGetPlane(drmmode->fd, kplane_res->planes[i]);
if (!kplane)
continue;
if (!(kplane->possible_crtcs & (1 << num)) ||
is_plane_assigned(drmmode->scrn, kplane->plane_id)) {
drmModeFreePlane(kplane);
continue;
}
plane_id = kplane->plane_id;
props = drmModeObjectGetProperties(drmmode->fd, plane_id,
DRM_MODE_OBJECT_PLANE);
if (!props) {
xf86DrvMsg(drmmode->scrn->scrnIndex, X_ERROR,
"couldn't get plane properties\n");
drmModeFreePlane(kplane);
continue;
}
drmmode_prop_info_update(drmmode, tmp_props, DRMMODE_PLANE__COUNT, props);
/* We need cursor planes only. */
type = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_TYPE],
props, DRMMODE_PLANE_TYPE__COUNT);
if (type != DRMMODE_PLANE_TYPE_CURSOR) {
drmModeFreePlane(kplane);
drmModeFreeObjectProperties(props);
continue;
}
int size_hint = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_SIZE_HINTS], props, 0);
populate_cursor_sizes(drmmode, drmmode_crtc, size_hint);
drmModeFreePlane(kplane);
drmModeFreeObjectProperties(props);
break;
}
drmmode_prop_info_free(tmp_props, DRMMODE_PLANE__COUNT);
drmModeFreePlaneResources(kplane_res);
}
#endif
static void
drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
{
@@ -2411,6 +2574,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
[DRMMODE_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
[DRMMODE_PLANE_CRTC_W] = { .name = "CRTC_W", },
[DRMMODE_PLANE_CRTC_H] = { .name = "CRTC_H", },
[DRMMODE_PLANE_SIZE_HINTS] = { .name = "SIZE_HINTS" }
};
drmmode_prop_info_rec tmp_props[DRMMODE_PLANE__COUNT];
@@ -2458,6 +2622,7 @@ drmmode_crtc_create_planes(xf86CrtcPtr crtc, int num)
/* Only primary planes are important for atomic page-flipping */
type = drmmode_prop_get_value(&tmp_props[DRMMODE_PLANE_TYPE],
props, DRMMODE_PLANE_TYPE__COUNT);
if (type != DRMMODE_PLANE_TYPE_PRIMARY) {
drmModeFreePlane(kplane);
drmModeFreeObjectProperties(props);
@@ -2560,7 +2725,7 @@ drmmode_crtc_vrr_init(int drm_fd, xf86CrtcPtr crtc)
}
static unsigned int
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, drmmode_cursor_dim_rec fallback, int num)
{
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
@@ -2587,6 +2752,13 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
xorg_list_init(&drmmode_crtc->tearfree.dri_flip_list);
drmmode_crtc->next_msc = UINT64_MAX;
/* Setup the fallback cursor immediately. */
drmmode_crtc->cursor.num_dimensions = 1;
drmmode_crtc->cursor.dimensions = xnfalloc(sizeof(drmmode_cursor_dim_rec));
drmmode_crtc->cursor.dimensions[0].width = fallback.width;
drmmode_crtc->cursor.dimensions[0].height = fallback.height;
props = drmModeObjectGetProperties(drmmode->fd, mode_res->crtcs[num],
DRM_MODE_OBJECT_CRTC);
if (!props || !drmmode_prop_info_copy(drmmode_crtc->props, crtc_props,
@@ -2600,6 +2772,11 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res
drmModeFreeObjectProperties(props);
drmmode_crtc_create_planes(crtc, num);
#ifdef LIBDRM_PLANE_SIZE_HINTS
/* Get the SIZE_HINT dimensions, if supported. */
drmmode_crtc_probe_size_hint(crtc, num);
#endif
/* Hide any cursors which may be active from previous users */
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0);
@@ -3905,12 +4082,29 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
"Up to %d crtcs needed for screen.\n", crtcs_needed);
/* This is the safest fallback value as
* it is the default value that KMS uses. */
drmmode_cursor_dim_rec fallback = {
.width = 64,
.height = 64,
};
ret = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_WIDTH, &value);
if (!ret) {
fallback.width = value;
}
ret = drmGetCap(drmmode->fd, DRM_CAP_CURSOR_HEIGHT, &value);
if (!ret) {
fallback.height = value;
}
xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width,
mode_res->max_height);
for (i = 0; i < mode_res->count_crtcs; i++)
if (!xf86IsEntityShared(pScrn->entityList[0]) ||
(crtcs_needed && !(ms_ent->assigned_crtcs & (1 << i))))
crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, fallback, i);
/* All ZaphodHeads outputs provided with matching crtcs? */
if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
@@ -4378,55 +4572,6 @@ drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
#endif
}
static void drmmode_probe_cursor_size(xf86CrtcPtr crtc)
{
modesettingPtr ms = modesettingPTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int width, height, size;
ms->min_cursor_width = ms->max_cursor_width;
ms->min_cursor_height = ms->max_cursor_height;
/* probe square min first */
for (size = 1; size <= ms->max_cursor_width &&
size <= ms->max_cursor_height; size *= 2) {
int ret;
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
handle, size, size, 0, 0);
if (ret == 0)
break;
}
/* check if smaller width works with non-square */
for (width = 1; width <= size; width *= 2) {
int ret;
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
handle, width, size, 0, 0);
if (ret == 0) {
ms->min_cursor_width = width;
break;
}
}
/* check if smaller height works with non-square */
for (height = 1; height <= size; height *= 2) {
int ret;
ret = drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
handle, size, height, 0, 0);
if (ret == 0) {
ms->min_cursor_height = height;
break;
}
}
drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, 0, 0);
}
/* create front and cursor BOs */
Bool
drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
@@ -4446,24 +4591,24 @@ drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
return FALSE;
pScrn->displayWidth = drmmode_bo_get_pitch(&drmmode->front_bo) / cpp;
width = ms->max_cursor_width;
height = ms->max_cursor_height;
bpp = 32;
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_cursor_rec cursor = drmmode_crtc->cursor;
/* If we don't have any dimensions then
* something has gone terribly wrong. */
assert(cursor.num_dimensions);
drmmode_crtc->cursor_bo =
dumb_bo_create(drmmode->fd, width, height, bpp);
/* Use the maximum available size. */
width = get_maximum_cursor_width(cursor);
height = get_maximum_cursor_height(cursor);
drmmode_crtc->cursor.bo = dumb_bo_create(drmmode->fd, width, height, bpp);
}
drmmode_probe_cursor_size(xf86_config->crtc[0]);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, MS_LOGLEVEL_DEBUG,
"Supported cursor sizes %dx%d -> %dx%d\n",
ms->min_cursor_width, ms->min_cursor_height,
ms->max_cursor_width, ms->max_cursor_height);
return TRUE;
}
@@ -4498,7 +4643,7 @@ drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
ret = dumb_bo_map(drmmode->fd, drmmode_crtc->cursor_bo);
ret = dumb_bo_map(drmmode->fd, drmmode_crtc->cursor.bo);
if (ret)
return FALSE;
}
@@ -4522,7 +4667,7 @@ drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
xf86CrtcPtr crtc = xf86_config->crtc[i];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor.bo);
drmmode_destroy_tearfree_shadow(crtc);
}
}
@@ -4598,7 +4743,7 @@ drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled)
drmmode_crtc->vrr_enabled = enabled;
}
Bool drmmode_get_cursor_limit(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim)
Bool drmmode_get_largest_cursor(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int max_width = 0, max_height = 0, i;
@@ -4611,15 +4756,14 @@ Bool drmmode_get_cursor_limit(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_l
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_cursor_rec cursor = drmmode_crtc->cursor;
/* Very ugly. */
/* Get the largest cursor available. */
drmmode_cursor_dim_rec largest = cursor.dimensions[cursor.num_dimensions - 1];
int width = largest.width;
int height = largest.height;
/**
* TODO: We should only let sizes that all CRTCs support.
*/
/* Future work:
* - We should only let sizes that all CRTCs support. */
if (width > max_width && height > max_height)
{
max_width = width;

View File

@@ -191,6 +191,7 @@ typedef struct {
typedef struct {
uint16_t num_dimensions;
/* Sorted from smallest to largest. */
drmmode_cursor_dim_rec* dimensions;
struct dumb_bo *bo;
} drmmode_cursor_rec, *drmmode_cursor_ptr;
@@ -200,7 +201,7 @@ typedef struct {
drmModeCrtcPtr mode_crtc;
uint32_t vblank_pipe;
int dpms_mode;
struct dumb_bo *cursor_bo;
drmmode_cursor_rec cursor;
Bool cursor_up;
uint16_t lut_r[256], lut_g[256], lut_b[256];
@@ -355,6 +356,6 @@ Bool drmmode_crtc_get_fb_id(xf86CrtcPtr crtc, uint32_t *fb_id, int *x, int *y);
void drmmode_set_dpms(ScrnInfoPtr scrn, int PowerManagementMode, int flags);
void drmmode_crtc_set_vrr(xf86CrtcPtr crtc, Bool enabled);
Bool drmmode_get_cursor_limit(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim);
Bool drmmode_get_largest_cursor(ScrnInfoPtr pScrn, drmmode_cursor_dim_ptr cursor_lim);
#endif

View File

@@ -101,6 +101,7 @@ conf_data.set('CONFIG_WSCONS', host_machine.system() in ['openbsd', 'netbsd'] ?
conf_data.set('HAVE_XSHMFENCE', xshmfence_dep.found() ? '1' : false)
conf_data.set('WITH_LIBDRM', libdrm_required ? '1' : false)
conf_data.set('LIBDRM_PLANE_SIZE_HINTS', libdrm_required ? libdrm_dep.version().version_compare('>= 2.4.122') : false)
conf_data.set('GLAMOR_HAS_EGL_QUERY_DMABUF',
epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.4.4') ? '1' : false)
conf_data.set('GLAMOR_HAS_EGL_QUERY_DRIVER',