mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +08:00
Merge remote-tracking branch 'origin/2.6.x' into feature/backmerge
This commit is contained in:
commit
dc9d794722
@ -69,9 +69,14 @@ sfml_set_option(SFML_BUILD_NETWORK TRUE BOOL "TRUE to build SFML's Network modul
|
|||||||
# add an option for building the API documentation
|
# add an option for building the API documentation
|
||||||
sfml_set_option(SFML_BUILD_DOC FALSE BOOL "TRUE to generate the API documentation, FALSE to ignore it")
|
sfml_set_option(SFML_BUILD_DOC FALSE BOOL "TRUE to generate the API documentation, FALSE to ignore it")
|
||||||
|
|
||||||
# add an option for choosing the OpenGL implementation
|
|
||||||
if(SFML_BUILD_WINDOW)
|
if(SFML_BUILD_WINDOW)
|
||||||
|
# add an option for choosing the OpenGL implementation
|
||||||
sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation")
|
sfml_set_option(SFML_OPENGL_ES ${OPENGL_ES} BOOL "TRUE to use an OpenGL ES implementation, FALSE to use a desktop OpenGL implementation")
|
||||||
|
|
||||||
|
# add an option for choosing whether to use the DRM windowing backend
|
||||||
|
if(SFML_OS_LINUX)
|
||||||
|
sfml_set_option(SFML_USE_DRM FALSE BOOL "TRUE to use DRM windowing backend")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# add an option for building the test suite
|
# add an option for building the test suite
|
||||||
|
364
extlibs/headers/drm/drm-common.c
vendored
364
extlibs/headers/drm/drm-common.c
vendored
@ -1,364 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Rob Clark <rclark@redhat.com>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the
|
|
||||||
* next paragraph) shall be included in all copies or substantial portions
|
|
||||||
* of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <drm-common.h>
|
|
||||||
#include <gbm.h>
|
|
||||||
|
|
||||||
#define WEAK __attribute__((weak))
|
|
||||||
|
|
||||||
WEAK uint64_t gbm_bo_get_modifier(struct gbm_bo *bo);
|
|
||||||
WEAK int gbm_bo_get_plane_count(struct gbm_bo *bo);
|
|
||||||
WEAK uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane);
|
|
||||||
WEAK uint32_t gbm_bo_get_offset(struct gbm_bo *bo, int plane);
|
|
||||||
|
|
||||||
static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
|
|
||||||
{
|
|
||||||
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
|
|
||||||
struct drm_fb *fb = data;
|
|
||||||
|
|
||||||
if (fb->fb_id)
|
|
||||||
drmModeRmFB(drm_fd, fb->fb_id);
|
|
||||||
|
|
||||||
free(fb);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo)
|
|
||||||
{
|
|
||||||
int drm_fd = gbm_device_get_fd(gbm_bo_get_device(bo));
|
|
||||||
struct drm_fb *fb = gbm_bo_get_user_data(bo);
|
|
||||||
uint32_t width, height, format,
|
|
||||||
strides[4] = {0}, handles[4] = {0},
|
|
||||||
offsets[4] = {0}, flags = 0;
|
|
||||||
int ret = -1;
|
|
||||||
|
|
||||||
if (fb)
|
|
||||||
return fb;
|
|
||||||
|
|
||||||
fb = calloc(1, sizeof *fb);
|
|
||||||
fb->bo = bo;
|
|
||||||
|
|
||||||
width = gbm_bo_get_width(bo);
|
|
||||||
height = gbm_bo_get_height(bo);
|
|
||||||
format = gbm_bo_get_format(bo);
|
|
||||||
|
|
||||||
if (gbm_bo_get_modifier && gbm_bo_get_plane_count &&
|
|
||||||
gbm_bo_get_stride_for_plane && gbm_bo_get_offset)
|
|
||||||
{
|
|
||||||
uint64_t modifiers[4] = {0};
|
|
||||||
modifiers[0] = gbm_bo_get_modifier(bo);
|
|
||||||
const int num_planes = gbm_bo_get_plane_count(bo);
|
|
||||||
for (int i = 0; i < num_planes; i++)
|
|
||||||
{
|
|
||||||
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
|
|
||||||
handles[i] = gbm_bo_get_handle(bo).u32;
|
|
||||||
offsets[i] = gbm_bo_get_offset(bo, i);
|
|
||||||
modifiers[i] = modifiers[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (modifiers[0])
|
|
||||||
{
|
|
||||||
flags = DRM_MODE_FB_MODIFIERS;
|
|
||||||
// printf("Using modifier %" PRIx64 "\n", modifiers[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = drmModeAddFB2WithModifiers(drm_fd, width, height,
|
|
||||||
format, handles, strides, offsets,
|
|
||||||
modifiers, &fb->fb_id, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
// if (flags)
|
|
||||||
// fprintf(stderr, "Modifiers failed!\n");
|
|
||||||
|
|
||||||
memcpy(handles, (uint32_t [4]){gbm_bo_get_handle(bo).u32,0,0,0}, 16);
|
|
||||||
memcpy(strides, (uint32_t [4]){gbm_bo_get_stride(bo),0,0,0}, 16);
|
|
||||||
memset(offsets, 0, 16);
|
|
||||||
ret = drmModeAddFB2(drm_fd, width, height, format,
|
|
||||||
handles, strides, offsets, &fb->fb_id, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
printf("failed to create fb: %s\n", strerror(errno));
|
|
||||||
free(fb);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
|
|
||||||
|
|
||||||
return fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t find_crtc_for_encoder(const drmModeRes *resources,
|
|
||||||
const drmModeEncoder *encoder)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int i = 0; i < resources->count_crtcs; i++)
|
|
||||||
{
|
|
||||||
/* possible_crtcs is a bitmask as described here:
|
|
||||||
* https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api
|
|
||||||
*/
|
|
||||||
const uint32_t crtc_mask = 1U << i;
|
|
||||||
const uint32_t crtc_id = resources->crtcs[i];
|
|
||||||
if (encoder->possible_crtcs & crtc_mask)
|
|
||||||
{
|
|
||||||
return crtc_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no match found */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t find_crtc_for_connector(const struct drm *drm, const drmModeRes *resources, const drmModeConnector *connector)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < connector->count_encoders; i++)
|
|
||||||
{
|
|
||||||
const uint32_t encoder_id = connector->encoders[i];
|
|
||||||
drmModeEncoder *encoder = drmModeGetEncoder(drm->fd, encoder_id);
|
|
||||||
|
|
||||||
if (encoder)
|
|
||||||
{
|
|
||||||
const uint32_t crtc_id = find_crtc_for_encoder(resources, encoder);
|
|
||||||
|
|
||||||
drmModeFreeEncoder(encoder);
|
|
||||||
if (crtc_id != 0)
|
|
||||||
{
|
|
||||||
return crtc_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no match found */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_resources(int fd, drmModeRes **resources)
|
|
||||||
{
|
|
||||||
*resources = drmModeGetResources(fd);
|
|
||||||
if (*resources == NULL)
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int has_monitor_connected(int fd, drmModeRes* resources)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
drmModeConnector *connector;
|
|
||||||
for (i = 0; i < resources->count_connectors; i++)
|
|
||||||
{
|
|
||||||
connector = drmModeGetConnector(fd, resources->connectors[i]);
|
|
||||||
if (connector->connection == DRM_MODE_CONNECTED)
|
|
||||||
{
|
|
||||||
/* There is a monitor connected */
|
|
||||||
drmModeFreeConnector(connector);
|
|
||||||
connector = NULL;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
drmModeFreeConnector(connector);
|
|
||||||
connector = NULL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_DRM_DEVICES 64
|
|
||||||
|
|
||||||
static int find_drm_device(drmModeRes **resources)
|
|
||||||
{
|
|
||||||
drmDevicePtr devices[MAX_DRM_DEVICES] = { NULL };
|
|
||||||
int num_devices, fd = -1;
|
|
||||||
|
|
||||||
num_devices = drmGetDevices2(0, devices, MAX_DRM_DEVICES);
|
|
||||||
if (num_devices < 0)
|
|
||||||
{
|
|
||||||
printf("drmGetDevices2 failed: %s\n", strerror(-num_devices));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < num_devices; i++)
|
|
||||||
{
|
|
||||||
drmDevicePtr device = devices[i];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!(device->available_nodes & (1 << DRM_NODE_PRIMARY)))
|
|
||||||
continue;
|
|
||||||
/* OK, it's a primary device. If we can get the
|
|
||||||
* drmModeResources, it means it's also a
|
|
||||||
* KMS-capable device.
|
|
||||||
*/
|
|
||||||
fd = open(device->nodes[DRM_NODE_PRIMARY], O_RDWR);
|
|
||||||
if (fd < 0)
|
|
||||||
continue;
|
|
||||||
ret = get_resources(fd, resources);
|
|
||||||
if(getenv("SFML_DRM_DEBUG"))
|
|
||||||
{
|
|
||||||
printf("DRM device used: %d\n", i);
|
|
||||||
}
|
|
||||||
if(!ret && has_monitor_connected(fd, *resources) != 0)
|
|
||||||
break;
|
|
||||||
close(fd);
|
|
||||||
fd = -1;
|
|
||||||
}
|
|
||||||
drmFreeDevices(devices, num_devices);
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
printf("no drm device found!\n");
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int init_drm(struct drm *drm, const char *device, const char *mode_str,
|
|
||||||
unsigned int vrefresh)
|
|
||||||
{
|
|
||||||
drmModeRes *resources;
|
|
||||||
drmModeConnector *connector = NULL;
|
|
||||||
drmModeEncoder *encoder = NULL;
|
|
||||||
int i, ret, area;
|
|
||||||
|
|
||||||
if (device)
|
|
||||||
{
|
|
||||||
drm->fd = open(device, O_RDWR);
|
|
||||||
ret = get_resources(drm->fd, &resources);
|
|
||||||
if (ret < 0 && errno == EOPNOTSUPP)
|
|
||||||
printf("%s does not look like a modeset device\n", device);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
drm->fd = find_drm_device(&resources);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drm->fd < 0)
|
|
||||||
{
|
|
||||||
printf("could not open drm device\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resources)
|
|
||||||
{
|
|
||||||
printf("drmModeGetResources failed: %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find a connected connector: */
|
|
||||||
for (i = 0; i < resources->count_connectors; i++)
|
|
||||||
{
|
|
||||||
connector = drmModeGetConnector(drm->fd, resources->connectors[i]);
|
|
||||||
if (connector->connection == DRM_MODE_CONNECTED)
|
|
||||||
{
|
|
||||||
/* it's connected, let's use this! */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
drmModeFreeConnector(connector);
|
|
||||||
connector = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!connector)
|
|
||||||
{
|
|
||||||
/* we could be fancy and listen for hotplug events and wait for
|
|
||||||
* a connector..
|
|
||||||
*/
|
|
||||||
printf("no connected connector!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find user requested mode: */
|
|
||||||
if (mode_str && *mode_str)
|
|
||||||
{
|
|
||||||
for (i = 0; i < connector->count_modes; i++)
|
|
||||||
{
|
|
||||||
drmModeModeInfo *current_mode = &connector->modes[i];
|
|
||||||
|
|
||||||
if (strcmp(current_mode->name, mode_str) == 0)
|
|
||||||
{
|
|
||||||
if (vrefresh == 0 || current_mode->vrefresh == vrefresh)
|
|
||||||
{
|
|
||||||
drm->mode = current_mode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!drm->mode)
|
|
||||||
printf("requested mode not found, using default mode!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find encoder: */
|
|
||||||
for (i = 0; i < resources->count_encoders; i++)
|
|
||||||
{
|
|
||||||
encoder = drmModeGetEncoder(drm->fd, resources->encoders[i]);
|
|
||||||
if (encoder->encoder_id == connector->encoder_id)
|
|
||||||
break;
|
|
||||||
drmModeFreeEncoder(encoder);
|
|
||||||
encoder = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encoder)
|
|
||||||
{
|
|
||||||
drm->crtc_id = encoder->crtc_id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t crtc_id = find_crtc_for_connector(drm, resources, connector);
|
|
||||||
if (crtc_id == 0)
|
|
||||||
{
|
|
||||||
printf("no crtc found!\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
drm->crtc_id = crtc_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
drmModeFreeResources(resources);
|
|
||||||
|
|
||||||
drm->connector_id = connector->connector_id;
|
|
||||||
|
|
||||||
drm->saved_connector = connector;
|
|
||||||
drm->saved_encoder = encoder;
|
|
||||||
|
|
||||||
// get original display mode so we can restore display mode after program exits
|
|
||||||
drm->original_crtc = drmModeGetCrtc(drm->fd, drm->crtc_id);
|
|
||||||
|
|
||||||
/* Let's use the current mode rather than the preferred one if the user didn't
|
|
||||||
* specify a mode with env vars
|
|
||||||
*/
|
|
||||||
if (!drm->mode)
|
|
||||||
{
|
|
||||||
if(getenv("SFML_DRM_DEBUG"))
|
|
||||||
printf("DRM using the current mode\n");
|
|
||||||
drm->mode = &(drm->original_crtc->mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getenv("SFML_DRM_DEBUG"))
|
|
||||||
{
|
|
||||||
printf("DRM Mode used: %s@%d\n", drm->mode->name, drm->mode->vrefresh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
86
extlibs/headers/drm/drm-common.h
vendored
86
extlibs/headers/drm/drm-common.h
vendored
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Rob Clark <rclark@redhat.com>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
* copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice (including the
|
|
||||||
* next paragraph) shall be included in all copies or substantial portions
|
|
||||||
* of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
||||||
* DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _DRM_COMMON_H
|
|
||||||
#define _DRM_COMMON_H
|
|
||||||
|
|
||||||
#include <xf86drm.h>
|
|
||||||
#include <xf86drmMode.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct gbm;
|
|
||||||
struct egl;
|
|
||||||
|
|
||||||
struct plane
|
|
||||||
{
|
|
||||||
drmModePlane *plane;
|
|
||||||
drmModeObjectProperties *props;
|
|
||||||
drmModePropertyRes **props_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct crtc
|
|
||||||
{
|
|
||||||
drmModeCrtc *crtc;
|
|
||||||
drmModeObjectProperties *props;
|
|
||||||
drmModePropertyRes **props_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct connector
|
|
||||||
{
|
|
||||||
drmModeConnector *connector;
|
|
||||||
drmModeObjectProperties *props;
|
|
||||||
drmModePropertyRes **props_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
drmModeModeInfo *mode;
|
|
||||||
uint32_t crtc_id;
|
|
||||||
uint32_t connector_id;
|
|
||||||
|
|
||||||
drmModeCrtcPtr original_crtc;
|
|
||||||
|
|
||||||
drmModeConnectorPtr saved_connector;
|
|
||||||
drmModeEncoderPtr saved_encoder;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_fb
|
|
||||||
{
|
|
||||||
struct gbm_bo *bo;
|
|
||||||
uint32_t fb_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo);
|
|
||||||
|
|
||||||
int init_drm(struct drm *drm, const char *device, const char *mode_str, unsigned int vrefresh);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _DRM_COMMON_H */
|
|
@ -72,6 +72,9 @@ public:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
/// \brief Check if a mouse button is pressed
|
/// \brief Check if a mouse button is pressed
|
||||||
///
|
///
|
||||||
|
/// \warning Checking the state of buttons Mouse::XButton1 and
|
||||||
|
/// Mouse::XButton2 is not supported on Linux with X11.
|
||||||
|
///
|
||||||
/// \param button Button to check
|
/// \param button Button to check
|
||||||
///
|
///
|
||||||
/// \return True if the button is pressed, false otherwise
|
/// \return True if the button is pressed, false otherwise
|
||||||
|
@ -274,13 +274,10 @@ sfml_add_library(Window
|
|||||||
# DRM libraries
|
# DRM libraries
|
||||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD OR SFML_OS_NETBSD)
|
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD OR SFML_OS_NETBSD)
|
||||||
if(SFML_USE_DRM)
|
if(SFML_USE_DRM)
|
||||||
target_sources(sfml-window PRIVATE $<TARGET_OBJECTS:drm-common>)
|
|
||||||
sfml_find_package(DRM INCLUDE "DRM_INCLUDE_DIR" LINK "DRM_LIBRARY")
|
sfml_find_package(DRM INCLUDE "DRM_INCLUDE_DIR" LINK "DRM_LIBRARY")
|
||||||
target_include_directories(sfml-window PRIVATE ${PROJECT_SOURCE_DIR}/extlibs/headers/drm ${DRM_INCLUDE_DIR}/libdrm)
|
target_include_directories(sfml-window PRIVATE ${DRM_INCLUDE_DIR}/libdrm)
|
||||||
sfml_find_package(GBM INCLUDE "GBM_INCLUDE_DIR" LINK "GBM_LIBRARY")
|
sfml_find_package(GBM INCLUDE "GBM_INCLUDE_DIR" LINK "GBM_LIBRARY")
|
||||||
target_link_libraries(sfml-window PRIVATE drm gbm EGL)
|
target_link_libraries(sfml-window PRIVATE drm gbm EGL)
|
||||||
add_library(drm-common OBJECT ${PROJECT_SOURCE_DIR}/extlibs/headers/drm/drm-common.c)
|
|
||||||
target_include_directories(drm-common PRIVATE ${PROJECT_SOURCE_DIR}/extlibs/headers/drm ${DRM_INCLUDE_DIR}/libdrm)
|
|
||||||
else()
|
else()
|
||||||
sfml_find_package(X11 INCLUDE "X11_INCLUDE_DIR" LINK "X11_X11_LIB" "X11_Xrandr_LIB" "X11_Xcursor_LIB")
|
sfml_find_package(X11 INCLUDE "X11_INCLUDE_DIR" LINK "X11_X11_LIB" "X11_Xrandr_LIB" "X11_Xcursor_LIB")
|
||||||
target_link_libraries(sfml-window PRIVATE X11)
|
target_link_libraries(sfml-window PRIVATE X11)
|
||||||
|
@ -34,8 +34,10 @@
|
|||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <xf86drm.h>
|
||||||
|
|
||||||
// We check for this definition in order to avoid multiple definitions of GLAD
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
// entities during unity builds of SFML.
|
// entities during unity builds of SFML.
|
||||||
@ -47,8 +49,14 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
struct DrmFb
|
||||||
|
{
|
||||||
|
gbm_bo* bo;
|
||||||
|
std::uint32_t fbId;
|
||||||
|
};
|
||||||
|
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
drm drmNode;
|
sf::priv::Drm drmNode;
|
||||||
drmEventContext drmEventCtx;
|
drmEventContext drmEventCtx;
|
||||||
pollfd pollFD;
|
pollfd pollFD;
|
||||||
gbm_device* gbmDevice = nullptr;
|
gbm_device* gbmDevice = nullptr;
|
||||||
@ -76,7 +84,7 @@ static bool waitForFlip(int timeout)
|
|||||||
|
|
||||||
if (pollFD.revents & POLLIN)
|
if (pollFD.revents & POLLIN)
|
||||||
{
|
{
|
||||||
drmHandleEvent(drmNode.fd, &drmEventCtx);
|
drmHandleEvent(drmNode.fileDescriptor, &drmEventCtx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -91,22 +99,18 @@ void cleanup()
|
|||||||
if (!initialized)
|
if (!initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Avoid a modeswitch if possible */
|
drmModeSetCrtc(drmNode.fileDescriptor,
|
||||||
if (drmNode.mode != &drmNode.original_crtc->mode)
|
drmNode.originalCrtc->crtc_id,
|
||||||
drmModeSetCrtc(drmNode.fd,
|
drmNode.originalCrtc->buffer_id,
|
||||||
drmNode.original_crtc->crtc_id,
|
drmNode.originalCrtc->x,
|
||||||
drmNode.original_crtc->buffer_id,
|
drmNode.originalCrtc->y,
|
||||||
drmNode.original_crtc->x,
|
&drmNode.connectorId,
|
||||||
drmNode.original_crtc->y,
|
1,
|
||||||
&drmNode.connector_id,
|
&drmNode.originalCrtc->mode);
|
||||||
1,
|
|
||||||
&drmNode.original_crtc->mode);
|
|
||||||
else if (getenv("SFML_DRM_DEBUG"))
|
|
||||||
printf("DRM keeping the same mode since using the original one\n");
|
|
||||||
|
|
||||||
drmModeFreeConnector(drmNode.saved_connector);
|
drmModeFreeConnector(drmNode.savedConnector);
|
||||||
drmModeFreeEncoder(drmNode.saved_encoder);
|
drmModeFreeEncoder(drmNode.savedEncoder);
|
||||||
drmModeFreeCrtc(drmNode.original_crtc);
|
drmModeFreeCrtc(drmNode.originalCrtc);
|
||||||
|
|
||||||
eglTerminate(display);
|
eglTerminate(display);
|
||||||
display = EGL_NO_DISPLAY;
|
display = EGL_NO_DISPLAY;
|
||||||
@ -114,10 +118,10 @@ void cleanup()
|
|||||||
gbm_device_destroy(gbmDevice);
|
gbm_device_destroy(gbmDevice);
|
||||||
gbmDevice = nullptr;
|
gbmDevice = nullptr;
|
||||||
|
|
||||||
close(drmNode.fd);
|
close(drmNode.fileDescriptor);
|
||||||
|
|
||||||
drmNode.fd = -1;
|
drmNode.fileDescriptor = -1;
|
||||||
drmNode.mode = 0;
|
drmNode.mode = 0;
|
||||||
|
|
||||||
pollFD = {};
|
pollFD = {};
|
||||||
drmEventCtx = {};
|
drmEventCtx = {};
|
||||||
@ -127,6 +131,306 @@ void cleanup()
|
|||||||
initialized = false;
|
initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drmFbDestroyCallback(gbm_bo* bo, void* data)
|
||||||
|
{
|
||||||
|
int drmFd = gbm_device_get_fd(gbm_bo_get_device(bo));
|
||||||
|
DrmFb* fb = static_cast<DrmFb*>(data);
|
||||||
|
|
||||||
|
if (fb->fbId)
|
||||||
|
drmModeRmFB(drmFd, fb->fbId);
|
||||||
|
|
||||||
|
delete fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrmFb* drmFbGetFromBo(gbm_bo& bo)
|
||||||
|
{
|
||||||
|
int drmFd = gbm_device_get_fd(gbm_bo_get_device(&bo));
|
||||||
|
DrmFb* fb = static_cast<DrmFb*>(gbm_bo_get_user_data(&bo));
|
||||||
|
if (fb)
|
||||||
|
return fb;
|
||||||
|
|
||||||
|
fb = new DrmFb();
|
||||||
|
fb->bo = &bo;
|
||||||
|
|
||||||
|
const std::uint32_t width = gbm_bo_get_width(&bo);
|
||||||
|
const std::uint32_t height = gbm_bo_get_height(&bo);
|
||||||
|
const std::uint32_t format = gbm_bo_get_format(&bo);
|
||||||
|
|
||||||
|
std::uint32_t strides[4] = {0};
|
||||||
|
std::uint32_t handles[4] = {0};
|
||||||
|
std::uint32_t offsets[4] = {0};
|
||||||
|
std::uint64_t modifiers[4] = {0};
|
||||||
|
modifiers[0] = gbm_bo_get_modifier(&bo);
|
||||||
|
const int num_planes = gbm_bo_get_plane_count(&bo);
|
||||||
|
for (int i = 0; i < num_planes; ++i)
|
||||||
|
{
|
||||||
|
strides[i] = gbm_bo_get_stride_for_plane(&bo, i);
|
||||||
|
handles[i] = gbm_bo_get_handle(&bo).u32;
|
||||||
|
offsets[i] = gbm_bo_get_offset(&bo, i);
|
||||||
|
modifiers[i] = modifiers[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t flags = 0;
|
||||||
|
if (modifiers[0])
|
||||||
|
{
|
||||||
|
flags = DRM_MODE_FB_MODIFIERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = drmModeAddFB2WithModifiers(drmFd, width, height, format, handles, strides, offsets, modifiers, &fb->fbId, flags);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
std::memset(handles, 0, 16);
|
||||||
|
handles[0] = gbm_bo_get_handle(&bo).u32;
|
||||||
|
std::memset(strides, 0, 16);
|
||||||
|
strides[0] = gbm_bo_get_stride(&bo);
|
||||||
|
std::memset(offsets, 0, 16);
|
||||||
|
result = drmModeAddFB2(drmFd, width, height, format, handles, strides, offsets, &fb->fbId, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
sf::err() << "Failed to create fb: " << std::strerror(errno) << std::endl;
|
||||||
|
delete fb;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbm_bo_set_user_data(&bo, fb, drmFbDestroyCallback);
|
||||||
|
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t findCrtcForEncoder(const drmModeRes& resources, const drmModeEncoder& encoder)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < resources.count_crtcs; ++i)
|
||||||
|
{
|
||||||
|
// Possible_crtcs is a bitmask as described here:
|
||||||
|
// https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api
|
||||||
|
const std::uint32_t crtcMask = 1U << i;
|
||||||
|
const std::uint32_t crtcId = resources.crtcs[i];
|
||||||
|
if (encoder.possible_crtcs & crtcMask)
|
||||||
|
{
|
||||||
|
return crtcId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match found
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t findCrtcForConnector(const sf::priv::Drm& drm, const drmModeRes& resources, const drmModeConnector& connector)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < connector.count_encoders; ++i)
|
||||||
|
{
|
||||||
|
const std::uint32_t encoderId = connector.encoders[i];
|
||||||
|
const drmModeEncoderPtr encoder = drmModeGetEncoder(drm.fileDescriptor, encoderId);
|
||||||
|
|
||||||
|
if (encoder)
|
||||||
|
{
|
||||||
|
const std::uint32_t crtcId = findCrtcForEncoder(resources, *encoder);
|
||||||
|
|
||||||
|
drmModeFreeEncoder(encoder);
|
||||||
|
if (crtcId != 0)
|
||||||
|
{
|
||||||
|
return crtcId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match found
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getResources(int fd, drmModeResPtr& resources)
|
||||||
|
{
|
||||||
|
resources = drmModeGetResources(fd);
|
||||||
|
if (resources == nullptr)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hasMonitorConnected(int fd, drmModeRes& resources)
|
||||||
|
{
|
||||||
|
drmModeConnectorPtr connector;
|
||||||
|
for (int i = 0; i < resources.count_connectors; ++i)
|
||||||
|
{
|
||||||
|
connector = drmModeGetConnector(fd, resources.connectors[i]);
|
||||||
|
if (connector->connection == DRM_MODE_CONNECTED)
|
||||||
|
{
|
||||||
|
// There is a monitor connected
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = nullptr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = nullptr;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int findDrmDevice(drmModeResPtr& resources)
|
||||||
|
{
|
||||||
|
static const int maxDrmDevices = 64;
|
||||||
|
|
||||||
|
drmDevicePtr devices[maxDrmDevices] = {nullptr};
|
||||||
|
|
||||||
|
const int numDevices = drmGetDevices2(0, devices, maxDrmDevices);
|
||||||
|
if (numDevices < 0)
|
||||||
|
{
|
||||||
|
sf::err() << "drmGetDevices2 failed: " << std::strerror(-numDevices) << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileDescriptor = -1;
|
||||||
|
for (int i = 0; i < numDevices; ++i)
|
||||||
|
{
|
||||||
|
drmDevicePtr device = devices[i];
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if (!(device->available_nodes & (1 << DRM_NODE_PRIMARY)))
|
||||||
|
continue;
|
||||||
|
// OK, it's a primary device. If we can get the drmModeResources, it means it's also a KMS-capable device.
|
||||||
|
fileDescriptor = open(device->nodes[DRM_NODE_PRIMARY], O_RDWR);
|
||||||
|
if (fileDescriptor < 0)
|
||||||
|
continue;
|
||||||
|
result = getResources(fileDescriptor, resources);
|
||||||
|
#ifdef SFML_DEBUG
|
||||||
|
sf::err() << "DRM device used: " << i << std::endl;
|
||||||
|
#endif
|
||||||
|
if (!result && hasMonitorConnected(fileDescriptor, *resources) != 0)
|
||||||
|
break;
|
||||||
|
close(fileDescriptor);
|
||||||
|
fileDescriptor = -1;
|
||||||
|
}
|
||||||
|
drmFreeDevices(devices, numDevices);
|
||||||
|
|
||||||
|
if (fileDescriptor < 0)
|
||||||
|
sf::err() << "No drm device found!" << std::endl;
|
||||||
|
return fileDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int initDrm(sf::priv::Drm& drm, const char* device, const char* modeStr, unsigned int vrefresh)
|
||||||
|
{
|
||||||
|
drmModeResPtr resources;
|
||||||
|
|
||||||
|
if (device)
|
||||||
|
{
|
||||||
|
drm.fileDescriptor = open(device, O_RDWR);
|
||||||
|
const int ret = getResources(drm.fileDescriptor, resources);
|
||||||
|
if (ret < 0 && errno == EOPNOTSUPP)
|
||||||
|
sf::err() << device << " does not look like a modeset device" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
drm.fileDescriptor = findDrmDevice(resources);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drm.fileDescriptor < 0)
|
||||||
|
{
|
||||||
|
sf::err() << "Could not open drm device" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resources)
|
||||||
|
{
|
||||||
|
sf::err() << "drmModeGetResources failed: " << std::strerror(errno) << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a connected connector:
|
||||||
|
drmModeConnectorPtr connector = nullptr;
|
||||||
|
for (int i = 0; i < resources->count_connectors; ++i)
|
||||||
|
{
|
||||||
|
connector = drmModeGetConnector(drm.fileDescriptor, resources->connectors[i]);
|
||||||
|
if (connector->connection == DRM_MODE_CONNECTED)
|
||||||
|
{
|
||||||
|
// It's connected, let's use this!
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
drmModeFreeConnector(connector);
|
||||||
|
connector = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connector)
|
||||||
|
{
|
||||||
|
// We could be fancy and listen for hotplug events and wait for a connector..
|
||||||
|
sf::err() << "No connected connector!" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find user requested mode:
|
||||||
|
if (modeStr && *modeStr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < connector->count_modes; ++i)
|
||||||
|
{
|
||||||
|
drmModeModeInfoPtr currentMode = &connector->modes[i];
|
||||||
|
|
||||||
|
if (std::strcmp(currentMode->name, modeStr) == 0)
|
||||||
|
{
|
||||||
|
if (vrefresh == 0 || currentMode->vrefresh == vrefresh)
|
||||||
|
{
|
||||||
|
drm.mode = currentMode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!drm.mode)
|
||||||
|
sf::err() << "Requested mode not found, using default mode!" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find encoder:
|
||||||
|
drmModeEncoderPtr encoder = nullptr;
|
||||||
|
for (int i = 0; i < resources->count_encoders; ++i)
|
||||||
|
{
|
||||||
|
encoder = drmModeGetEncoder(drm.fileDescriptor, resources->encoders[i]);
|
||||||
|
if (encoder->encoder_id == connector->encoder_id)
|
||||||
|
break;
|
||||||
|
drmModeFreeEncoder(encoder);
|
||||||
|
encoder = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder)
|
||||||
|
{
|
||||||
|
drm.crtcId = encoder->crtc_id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::uint32_t crtcId = findCrtcForConnector(drm, *resources, *connector);
|
||||||
|
if (crtcId == 0)
|
||||||
|
{
|
||||||
|
sf::err() << "No crtc found!" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm.crtcId = crtcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
drmModeFreeResources(resources);
|
||||||
|
|
||||||
|
drm.connectorId = connector->connector_id;
|
||||||
|
|
||||||
|
drm.savedConnector = connector;
|
||||||
|
drm.savedEncoder = encoder;
|
||||||
|
|
||||||
|
// Get original display mode so we can restore display mode after program exits
|
||||||
|
drm.originalCrtc = drmModeGetCrtc(drm.fileDescriptor, drm.crtcId);
|
||||||
|
|
||||||
|
// Let's use the current mode rather than the preferred one if the user didn't specify a mode with env vars
|
||||||
|
if (!drm.mode)
|
||||||
|
{
|
||||||
|
#ifdef SFML_DEBUG
|
||||||
|
sf::err() << "DRM using the current mode" << std::endl;
|
||||||
|
#endif
|
||||||
|
drm.mode = &(drm.originalCrtc->mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SFML_DEBUG
|
||||||
|
sf::err() << "DRM Mode used: " << drm.mode->name << "@" << drm.mode->vrefresh << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void checkInit()
|
void checkInit()
|
||||||
{
|
{
|
||||||
if (initialized)
|
if (initialized)
|
||||||
@ -149,27 +453,26 @@ void checkInit()
|
|||||||
if (refreshString)
|
if (refreshString)
|
||||||
refreshRate = static_cast<unsigned int>(atoi(refreshString));
|
refreshRate = static_cast<unsigned int>(atoi(refreshString));
|
||||||
|
|
||||||
if (init_drm(&drmNode,
|
if (initDrm(drmNode,
|
||||||
deviceString, // device
|
deviceString, // device
|
||||||
modeString, // requested mode
|
modeString, // requested mode
|
||||||
refreshRate) < 0) // screen refresh rate
|
refreshRate) < 0) // screen refresh rate
|
||||||
{
|
{
|
||||||
sf::err() << "Error initializing DRM" << std::endl;
|
sf::err() << "Error initializing DRM" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gbmDevice = gbm_create_device(drmNode.fd);
|
gbmDevice = gbm_create_device(drmNode.fileDescriptor);
|
||||||
|
|
||||||
std::atexit(cleanup);
|
std::atexit(cleanup);
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
pollFD.fd = drmNode.fd;
|
pollFD.fd = drmNode.fileDescriptor;
|
||||||
pollFD.events = POLLIN;
|
pollFD.events = POLLIN;
|
||||||
drmEventCtx.version = 2;
|
drmEventCtx.version = 2;
|
||||||
drmEventCtx.page_flip_handler = pageFlipHandler;
|
drmEventCtx.page_flip_handler = pageFlipHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EGLDisplay getInitializedDisplay()
|
EGLDisplay getInitializedDisplay()
|
||||||
{
|
{
|
||||||
checkInit();
|
checkInit();
|
||||||
@ -360,7 +663,7 @@ void DRMContext::display()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle display of buffer to the screen
|
// Handle display of buffer to the screen
|
||||||
drm_fb* fb = nullptr;
|
DrmFb* fb = nullptr;
|
||||||
|
|
||||||
if (!waitForFlip(-1))
|
if (!waitForFlip(-1))
|
||||||
return;
|
return;
|
||||||
@ -381,7 +684,7 @@ void DRMContext::display()
|
|||||||
if (!m_nextBO)
|
if (!m_nextBO)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fb = drm_fb_get_from_bo(m_nextBO);
|
fb = drmFbGetFromBo(*m_nextBO);
|
||||||
if (!fb)
|
if (!fb)
|
||||||
{
|
{
|
||||||
err() << "Failed to get FB from buffer object" << std::endl;
|
err() << "Failed to get FB from buffer object" << std::endl;
|
||||||
@ -391,7 +694,7 @@ void DRMContext::display()
|
|||||||
// If first time, need to first call drmModeSetCrtc()
|
// If first time, need to first call drmModeSetCrtc()
|
||||||
if (!m_shown)
|
if (!m_shown)
|
||||||
{
|
{
|
||||||
if (drmModeSetCrtc(drmNode.fd, drmNode.crtc_id, fb->fb_id, 0, 0, &drmNode.connector_id, 1, drmNode.mode))
|
if (drmModeSetCrtc(drmNode.fileDescriptor, drmNode.crtcId, fb->fbId, 0, 0, &drmNode.connectorId, 1, drmNode.mode))
|
||||||
{
|
{
|
||||||
err() << "Failed to set mode: " << std::strerror(errno) << std::endl;
|
err() << "Failed to set mode: " << std::strerror(errno) << std::endl;
|
||||||
std::abort();
|
std::abort();
|
||||||
@ -400,7 +703,7 @@ void DRMContext::display()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do page flip
|
// Do page flip
|
||||||
if (!drmModePageFlip(drmNode.fd, drmNode.crtc_id, fb->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &waitingForFlip))
|
if (!drmModePageFlip(drmNode.fileDescriptor, drmNode.crtcId, fb->fbId, DRM_MODE_PAGE_FLIP_EVENT, &waitingForFlip))
|
||||||
waitingForFlip = 1;
|
waitingForFlip = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,10 +852,10 @@ GlFunctionPointer DRMContext::getFunction(const char* name)
|
|||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
drm* DRMContext::getDRM()
|
Drm& DRMContext::getDRM()
|
||||||
{
|
{
|
||||||
checkInit();
|
checkInit();
|
||||||
return &drmNode;
|
return drmNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace priv
|
} // namespace priv
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
|
|
||||||
#include <glad/egl.h>
|
#include <glad/egl.h>
|
||||||
|
|
||||||
#include <drm-common.h>
|
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
|
|
||||||
@ -45,6 +44,20 @@ namespace sf
|
|||||||
{
|
{
|
||||||
namespace priv
|
namespace priv
|
||||||
{
|
{
|
||||||
|
struct Drm
|
||||||
|
{
|
||||||
|
int fileDescriptor;
|
||||||
|
|
||||||
|
drmModeModeInfoPtr mode;
|
||||||
|
std::uint32_t crtcId;
|
||||||
|
std::uint32_t connectorId;
|
||||||
|
|
||||||
|
drmModeCrtcPtr originalCrtc;
|
||||||
|
|
||||||
|
drmModeConnectorPtr savedConnector;
|
||||||
|
drmModeEncoderPtr savedEncoder;
|
||||||
|
};
|
||||||
|
|
||||||
class WindowImplDRM;
|
class WindowImplDRM;
|
||||||
|
|
||||||
class DRMContext : public GlContext
|
class DRMContext : public GlContext
|
||||||
@ -174,7 +187,7 @@ protected:
|
|||||||
/// \brief Get Direct Rendering Manager pointer
|
/// \brief Get Direct Rendering Manager pointer
|
||||||
///
|
///
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
static drm* getDRM();
|
static Drm& getDRM();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
#include <SFML/Window/DRM/DRMContext.hpp>
|
#include <SFML/Window/DRM/DRMContext.hpp>
|
||||||
#include <SFML/Window/VideoModeImpl.hpp>
|
#include <SFML/Window/VideoModeImpl.hpp>
|
||||||
|
|
||||||
#include <drm-common.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -41,8 +39,8 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
|||||||
{
|
{
|
||||||
std::vector<VideoMode> modes;
|
std::vector<VideoMode> modes;
|
||||||
|
|
||||||
drm* drm = sf::priv::DRMContext::getDRM();
|
Drm& drm = sf::priv::DRMContext::getDRM();
|
||||||
drmModeConnectorPtr conn = drm->saved_connector;
|
drmModeConnectorPtr conn = drm.savedConnector;
|
||||||
|
|
||||||
if (conn)
|
if (conn)
|
||||||
{
|
{
|
||||||
@ -59,8 +57,8 @@ std::vector<VideoMode> VideoModeImpl::getFullscreenModes()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
VideoMode VideoModeImpl::getDesktopMode()
|
VideoMode VideoModeImpl::getDesktopMode()
|
||||||
{
|
{
|
||||||
drm* drm = sf::priv::DRMContext::getDRM();
|
Drm& drm = sf::priv::DRMContext::getDRM();
|
||||||
drmModeModeInfoPtr ptr = drm->mode;
|
drmModeModeInfoPtr ptr = drm.mode;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
return VideoMode({ptr->hdisplay, ptr->vdisplay});
|
return VideoMode({ptr->hdisplay, ptr->vdisplay});
|
||||||
else
|
else
|
||||||
|
@ -32,8 +32,6 @@
|
|||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include <SFML/Window/WindowStyle.hpp>
|
#include <SFML/Window/WindowStyle.hpp>
|
||||||
|
|
||||||
#include <drm-common.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -64,8 +62,8 @@ WindowImplDRM::~WindowImplDRM()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
WindowHandle WindowImplDRM::getSystemHandle() const
|
WindowHandle WindowImplDRM::getSystemHandle() const
|
||||||
{
|
{
|
||||||
drm* drm = sf::priv::DRMContext::getDRM();
|
Drm& drm = sf::priv::DRMContext::getDRM();
|
||||||
return static_cast<WindowHandle>(drm->fd);
|
return static_cast<WindowHandle>(drm.fileDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <SFML/Window/Unix/InputImpl.hpp>
|
#include <SFML/Window/Unix/InputImpl.hpp>
|
||||||
#include <SFML/Window/Window.hpp>
|
#include <SFML/Window/Window.hpp>
|
||||||
@ -207,6 +206,9 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
|||||||
// Close the connection with the X server
|
// Close the connection with the X server
|
||||||
closeDisplay(display);
|
closeDisplay(display);
|
||||||
|
|
||||||
|
// Buttons 4 and 5 are the vertical wheel and 6 and 7 the horizontal wheel.
|
||||||
|
// There is no mask for buttons 8 and 9, so checking the state of buttons
|
||||||
|
// Mouse::XButton1 and Mouse::XButton2 is not supported.
|
||||||
// clang-format off
|
// clang-format off
|
||||||
switch (button)
|
switch (button)
|
||||||
{
|
{
|
||||||
|
@ -2030,8 +2030,7 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
|
|||||||
// Mouse button pressed
|
// Mouse button pressed
|
||||||
case ButtonPress:
|
case ButtonPress:
|
||||||
{
|
{
|
||||||
// XXX: Why button 8 and 9?
|
// Buttons 4 and 5 are the vertical wheel and 6 and 7 the horizontal wheel.
|
||||||
// Because 4 and 5 are the vertical wheel and 6 and 7 are horizontal wheel ;)
|
|
||||||
unsigned int button = windowEvent.xbutton.button;
|
unsigned int button = windowEvent.xbutton.button;
|
||||||
if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9))
|
if ((button == Button1) || (button == Button2) || (button == Button3) || (button == 8) || (button == 9))
|
||||||
{
|
{
|
||||||
|
@ -85,8 +85,12 @@ void setProcessDpiAware()
|
|||||||
{
|
{
|
||||||
// We only check for E_INVALIDARG because we would get
|
// We only check for E_INVALIDARG because we would get
|
||||||
// E_ACCESSDENIED if the DPI was already set previously
|
// E_ACCESSDENIED if the DPI was already set previously
|
||||||
// and S_OK means the call was successful
|
// and S_OK means the call was successful.
|
||||||
if (SetProcessDpiAwarenessFunc(ProcessSystemDpiAware) == E_INVALIDARG)
|
// We intentionally don't use Per Monitor V2 which can be
|
||||||
|
// enabled with SetProcessDpiAwarenessContext, because that
|
||||||
|
// would scale the title bar and thus change window size
|
||||||
|
// by default when moving the window between monitors.
|
||||||
|
if (SetProcessDpiAwarenessFunc(ProcessPerMonitorDpiAware) == E_INVALIDARG)
|
||||||
{
|
{
|
||||||
sf::err() << "Failed to set process DPI awareness" << std::endl;
|
sf::err() << "Failed to set process DPI awareness" << std::endl;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user