Compare commits

...

3 Commits

Author SHA1 Message Date
Camilla Löwy
4e1d7e9266 Cleanup
Related to #786.
2017-09-17 21:20:12 +02:00
Camilla Löwy
243db302bf EGLDevice: Fix build after rebase
Some minor bitrot had occurred since the patch was made.

Related to #786.
2017-09-17 21:17:42 +02:00
Kamal
5b1a187f71 Add EGLDevice backend to GLFW
This adds interface to graphics application to create EGLDisplay
directly over GPU device as enabled by EGLDevice extensions

Fixes #786.
2017-09-17 21:17:42 +02:00
12 changed files with 1096 additions and 5 deletions

View File

@ -41,8 +41,9 @@ if (WIN32)
endif()
if (UNIX AND NOT APPLE)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
option(GLFW_USE_WAYLAND "Use Wayland for window creation" OFF)
option(GLFW_USE_MIR "Use Mir for window creation" OFF)
option(GLFW_USE_EGLDEVICE "Use EGLDevice for window creation" OFF)
endif()
if (MSVC)
@ -163,6 +164,9 @@ elseif (GLFW_USE_MIR)
elseif (GLFW_USE_OSMESA)
set(_GLFW_OSMESA 1)
message(STATUS "Using OSMesa for headless context creation")
elseif (GLFW_USE_EGLDEVICE)
set(_GLFW_EGLDEVICE 1)
message(STATUS "Using EGLDevice for window creation")
elseif (WIN32)
set(_GLFW_WIN32 1)
message(STATUS "Using Win32 for window creation")
@ -291,6 +295,23 @@ if (_GLFW_WAYLAND)
list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}")
endif()
#--------------------------------------------------------------------
# Use EGLDevice for window creation
#--------------------------------------------------------------------
if (_GLFW_EGLDEVICE)
find_path(DRM_INCLUDE_DIR NAMES drm.h PATH_SUFFIXES drm libdrm)
if (NOT DRM_INCLUDE_DIR)
message(FATAL_ERROR "The libdrm headers were not found")
endif()
list(APPEND glfw_INCLUDE_DIRS "${DRM_INCLUDE_DIR}")
list(APPEND glfw_LIBRARIES "-ldrm")
list(APPEND glfw_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
endif()
#--------------------------------------------------------------------
# Use Mir for window creation
#--------------------------------------------------------------------

View File

@ -11,8 +11,9 @@ application development. It provides a simple, platform-independent API for
creating windows, contexts and surfaces, reading input, handling events, etc.
GLFW natively supports Windows, macOS and Linux and other Unix-like systems.
Experimental implementations for the Wayland protocol and the Mir display server
are available but not yet officially supported.
Experimental implementations for the Wayland protocol, the Mir display server
and direct rendering via EGLDevice are available but not yet officially
supported.
GLFW is licensed under the [zlib/libpng
license](http://www.glfw.org/license.html).
@ -91,6 +92,9 @@ GLFW itself depends only on the headers and libraries for your window system.
The (experimental) Wayland backend also depends on the `extra-cmake-modules`
package, which is used to generated Wayland protocol headers.
The (experimental) EGLDevice backend also depends on the `libdrm-dev`
development package.
The examples and test programs depend on a number of tiny libraries. These are
located in the `deps/` directory.
@ -208,6 +212,7 @@ information on what to include when reporting a bug.
- [X11] Bugfix: Incremental reading of selections was not supported (#275)
- [X11] Bugfix: Selection I/O reported but did not support `COMPOUND_TEXT`
- [X11] Bugfix: Latin-1 text read from selections was not converted to UTF-8
- [Linux] Added experimental support for direct rendering via EGLDevice (#786)
- [Linux] Moved to evdev for joystick input (#906,#1005)
- [Linux] Bugfix: Event processing did not detect joystick disconnection (#932)
- [Linux] Bugfix: The joystick device path could be truncated (#1025)
@ -282,6 +287,7 @@ skills.
- David Carlier
- Arturo Castro
- Chi-kwan Chan
- Kamal Chandra
- Ian Clarkson
- Michał Cichoń
- Lambert Clara

View File

@ -257,6 +257,7 @@ ramps and clipboard. The options are:
- @b _GLFW_WAYLAND to use the Wayland API (experimental and incomplete)
- @b _GLFW_MIR to use the Mir API (experimental and incomplete)
- @b _GLFW_OSMESA to use the OSMesa API (headless and non-interactive)
- @b _GLFW_EGLDEVICE to use the EGLDevice API (experimental and incomplete)
If you are building GLFW as a shared library / dynamic library / DLL then you
must also define @b _GLFW_BUILD_DLL. Otherwise, you must not define it.

View File

@ -47,6 +47,12 @@ elseif (_GLFW_WAYLAND)
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
BASENAME pointer-constraints-unstable-v1)
elseif(_GLFW_EGLDEVICE)
set(glfw_HEADERS ${common_HEADERS} egldevice_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h)
set(glfw_SOURCES ${common_SOURCES} egldevice_init.c egldevice_monitor.c egldevice_window.c
linux_joystick.c posix_time.c posix_thread.c xkb_unicode.c
egl_context.c)
elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
@ -88,7 +94,7 @@ set_target_properties(glfw PROPERTIES
target_compile_definitions(glfw PRIVATE
_GLFW_USE_CONFIG_H
$<$<BOOL:${UNIX}>:_XOPEN_SOURCE=600>)
$<$<BOOL:${UNIX}>:_POSIX_C_SOURCE=200809L>)
target_include_directories(glfw PUBLIC
"$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>")

View File

@ -116,10 +116,18 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
continue;
#if defined(_GLFW_EGLDEVICE)
// Only consider stream EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_STREAM_BIT_KHR))
continue;
#else
// Only consider window EGLConfigs
if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
continue;
#endif
#if defined(_GLFW_X11)
// Only consider EGLConfigs with associated Visuals
if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
@ -376,6 +384,9 @@ GLFWbool _glfwInitEGL(void)
return GLFW_FALSE;
}
// For EGLDevice backend the display gets initialized
// in _glfwPlatformInit()
#if !defined(_GLFW_EGLDEVICE)
_glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
if (_glfw.egl.display == EGL_NO_DISPLAY)
{
@ -396,6 +407,7 @@ GLFWbool _glfwInitEGL(void)
_glfwTerminateEGL();
return GLFW_FALSE;
}
#endif
_glfw.egl.KHR_create_context =
extensionSupportedEGL("EGL_KHR_create_context");
@ -581,6 +593,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
setAttrib(EGL_NONE, EGL_NONE);
}
// The surface for EGLDevice backened is created in _glfwPlatformCreateWindow
//
#if !defined (_GLFW_EGLDEVICE)
window->context.egl.surface =
eglCreateWindowSurface(_glfw.egl.display,
config,
@ -593,6 +608,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
getEGLErrorString(eglGetError()));
return GLFW_FALSE;
}
#endif
window->context.egl.config = config;

View File

@ -47,6 +47,10 @@ typedef struct wl_egl_window* EGLNativeWindowType;
#define EGLAPIENTRY
typedef MirEGLNativeDisplayType EGLNativeDisplayType;
typedef MirEGLNativeWindowType EGLNativeWindowType;
#elif defined(_GLFW_EGLDEVICE)
#define EGLAPIENTRY
typedef void* EGLNativeDisplayType;
typedef int EGLNativeWindowType;
#else
#error "No supported EGL platform selected"
#endif
@ -84,6 +88,8 @@ typedef MirEGLNativeWindowType EGLNativeWindowType;
#define EGL_OPENGL_ES_API 0x30a0
#define EGL_OPENGL_API 0x30a2
#define EGL_NONE 0x3038
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
#define EGL_EXTENSIONS 0x3055
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
#define EGL_NATIVE_VISUAL_ID 0x302e
@ -118,6 +124,7 @@ typedef void* EGLConfig;
typedef void* EGLContext;
typedef void* EGLDisplay;
typedef void* EGLSurface;
typedef intptr_t EGLAttrib;
// EGL function pointer typedefs
typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);

284
src/egldevice_init.c Normal file
View File

@ -0,0 +1,284 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#include <linux/limits.h>
static GLFWbool initializeExtensions(void)
{
_glfw.egldevice.QueryDevicesEXT =
(PFNEGLQUERYDEVICESEXTPROC)
eglGetProcAddress("eglQueryDevicesEXT");
_glfw.egldevice.QueryDeviceStringEXT =
(PFNEGLQUERYDEVICESTRINGEXTPROC)
eglGetProcAddress("eglQueryDeviceStringEXT");
_glfw.egldevice.GetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)
eglGetProcAddress("eglGetPlatformDisplayEXT");
_glfw.egldevice.GetOutputLayersEXT =
(PFNEGLGETOUTPUTLAYERSEXTPROC)
eglGetProcAddress("eglGetOutputLayersEXT");
_glfw.egldevice.CreateStreamKHR =
(PFNEGLCREATESTREAMKHRPROC)
eglGetProcAddress("eglCreateStreamKHR");
_glfw.egldevice.DestroyStreamKHR =
(PFNEGLDESTROYSTREAMKHRPROC)
eglGetProcAddress("eglDestroyStreamKHR");
_glfw.egldevice.StreamConsumerOutputEXT =
(PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)
eglGetProcAddress("eglStreamConsumerOutputEXT");
_glfw.egldevice.CreateStreamProducerSurfaceKHR =
(PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)
eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
if(!_glfw.egldevice.QueryDevicesEXT ||
!_glfw.egldevice.QueryDeviceStringEXT ||
!_glfw.egldevice.GetPlatformDisplayEXT ||
!_glfw.egldevice.GetOutputLayersEXT ||
!_glfw.egldevice.CreateStreamKHR ||
!_glfw.egldevice.DestroyStreamKHR ||
!_glfw.egldevice.StreamConsumerOutputEXT ||
!_glfw.egldevice.CreateStreamProducerSurfaceKHR)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Failed to find required EGL extension functions");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
static EGLDeviceEXT getEGLDevice(void)
{
int i, num_devs;
EGLDeviceEXT* egl_devs, eglDevice;
const char *clientExtensionString;
eglDevice = EGL_NO_DEVICE_EXT;
clientExtensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!_glfwStringInExtensionString("EGL_EXT_device_base",
clientExtensionString) &&
(!_glfwStringInExtensionString("EGL_EXT_device_enumeration",
clientExtensionString) ||
!_glfwStringInExtensionString("EGL_EXT_device_query",
clientExtensionString)))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: EGL_EXT_device base extensions not found");
}
if (!eglQueryDevicesEXT(0, NULL, &num_devs))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Falied to query EGLDevice");
}
if (num_devs < 1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: No devices found");
}
egl_devs = calloc(sizeof(EGLDeviceEXT), num_devs);
if (egl_devs == NULL)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to allocate memory for device storage");
}
// Select suitable device
if (!eglQueryDevicesEXT(num_devs, egl_devs, &num_devs))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Failed to query EGL devices");
}
for (i = 0; i <= num_devs; i++)
{
const char* deviceExtensionString;
deviceExtensionString = eglQueryDeviceStringEXT(egl_devs[i], EGL_EXTENSIONS);
if (_glfwStringInExtensionString("EGL_EXT_device_drm",
deviceExtensionString))
{
eglDevice = egl_devs[i];
break;
}
}
free(egl_devs);
if (eglDevice == EGL_NO_DEVICE_EXT)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_device_drm");
}
return eglDevice;
}
static int getDRMFd(EGLDeviceEXT eglDevice)
{
int drm_fd;
const char* drmName;
drmName = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT);
if (!drmName || (strnlen(drmName, PATH_MAX) == 0))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain device file from 0x%p",
(void*)(uintptr_t)eglDevice);
}
drm_fd = drmOpen(drmName, NULL);
if (drm_fd < 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't open device file '%s'", drmName);
}
return drm_fd;
}
static GLFWbool initEGLDisplay(EGLDeviceEXT egl_dev, int drm_fd)
{
const char* displayExtensionString;
EGLint displayAttribs[] = {
EGL_DRM_MASTER_FD_EXT,
drm_fd,
EGL_NONE
};
_glfw.egl.display = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,
(void*)egl_dev,
displayAttribs);
if (_glfw.egl.display == EGL_NO_DISPLAY)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain EGLDisplay for device");
return GLFW_FALSE;
}
if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
{
_glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL");
return GLFW_FALSE;
}
// Check for stream_consumer_egloutput + output_drm support
displayExtensionString = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
if (!_glfwStringInExtensionString("EGL_EXT_output_base",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_output_base");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_EXT_output_drm",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_output_drm");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_KHR_stream",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_KHR_stream");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_KHR_stream_producer_eglsurface",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_KHR_stream_producer_eglsurface");
return GLFW_FALSE;
}
if (!_glfwStringInExtensionString("EGL_EXT_stream_consumer_egloutput",
displayExtensionString))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Missing required extension EGL_EXT_stream_consumer_egloutput");
return GLFW_FALSE;
}
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
{
EGLDeviceEXT egl_dev;
int drm_fd;
// Initialize EGL
if (!_glfwInitEGL())
return GLFW_FALSE;
// Initialize global data and extension function pointers
if (!initializeExtensions())
return GLFW_FALSE;
// Query and Obtain EGLDevice
egl_dev = getEGLDevice();
// Obtain and open DRM device file
drm_fd = getDRMFd(egl_dev);
// Store for use later
_glfw.egldevice.drmFd = drm_fd;
// Obtain EGLDisplay
if (!initEGLDisplay(egl_dev, drm_fd))
return GLFW_FALSE;
_glfwInitTimerPOSIX();
_glfwPollMonitorsEGLDevice();
return GLFW_TRUE;
}
void _glfwPlatformTerminate(void)
{
_glfwTerminateEGL();
_glfwTerminateJoysticksLinux();
}
const char* _glfwPlatformGetVersionString(void)
{
return _GLFW_VERSION_NUMBER "EGLDevice EGL"
#if defined(_GLFW_BUILD_DLL)
" shared"
#endif
;
}

165
src/egldevice_monitor.c Normal file
View File

@ -0,0 +1,165 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
static GLFWbool pickConnector(_GLFWmonitor* monitor, int drm_fd, drmModeRes* res_info)
{
int i, j;
// Getting suitable connector, encoder and crtc
for (i = 0; i < res_info->count_connectors; i++)
{
monitor->egldevice.connId = res_info->connectors[i];
drmModeConnector* conn_info;
conn_info =
drmModeGetConnector(drm_fd, monitor->egldevice.connId);
if (!conn_info)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to obtain info for connector (%d)",
monitor->egldevice.connId);
return GLFW_FALSE;
}
if (conn_info->connection == DRM_MODE_CONNECTED &&
conn_info->count_modes > 0 &&
conn_info->count_encoders > 0)
{
monitor->egldevice.encId = conn_info->encoders[0];
drmModeEncoder* enc_info;
enc_info =
drmModeGetEncoder(drm_fd, monitor->egldevice.encId);
if (!enc_info) {
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to query DRM-KMS information for connector index %d", i);
}
// Select the modesize
monitor->currentMode.width = (int)conn_info->modes[0].hdisplay;
monitor->currentMode.height = (int)conn_info->modes[0].vdisplay;
monitor->currentMode.refreshRate = (int)conn_info->modes[0].vrefresh;
monitor->modeCount = (int)conn_info->count_modes;
monitor->name = conn_info->modes[0].name;
for (j = 0; j < res_info->count_crtcs; j++)
{
if ((enc_info->possible_crtcs & (1 << j)) == 0)
continue;
monitor->egldevice.crtcId = res_info->crtcs[j];
monitor->egldevice.crtcIndex = j;
if (res_info->crtcs[i] == enc_info->crtc_id)
break;
}
if (monitor->egldevice.crtcId == 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to select suitable CRTC");
return GLFW_FALSE;
}
drmModeFreeEncoder(enc_info);
}
drmModeFreeConnector(conn_info);
}
return GLFW_TRUE;
}
static GLFWbool initDRMResources(_GLFWmonitor* monitor, int drm_fd)
{
drmModeRes* res_info;
res_info = drmModeGetResources(drm_fd);
if (!res_info)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Couldn't obtain DRM-KMS resources");
return GLFW_FALSE;
}
if(!pickConnector(monitor, drm_fd, res_info))
return GLFW_FALSE;
drmModeFreeResources(res_info);
return GLFW_TRUE;
}
/////////////////////////////////////////////////////////////////////////////
/////////// GLFW platform API //////////////
/////////////////////////////////////////////////////////////////////////////
void _glfwPollMonitorsEGLDevice(void)
{
_GLFWmonitor* monitor = _glfwAllocMonitor("Monitor", 0, 0);
// Obtain DRM resource info
if (!initDRMResources(monitor, _glfw.egldevice.drmFd))
{
_glfwFreeMonitor(monitor);
return;
}
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
}
void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetMonitorPos not implemented");
}
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetVideoModes not implemented");
*found = 0;
return NULL;
}
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetVideoMode not implemented");
}
void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetGammaRamp not implemented");
}
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetGammaRamp not implemented");
}

151
src/egldevice_platform.h Normal file
View File

@ -0,0 +1,151 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/select.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <dlfcn.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm_fourcc.h>
#include "posix_time.h"
#include "linux_joystick.h"
#include "posix_thread.h"
#include "egl_context.h"
#include "osmesa_context.h"
#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT) 0)
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
#define EGL_PLATFORM_DEVICE_EXT 0x313f
#define EGL_DRM_MASTER_FD_EXT 0x333c
#define EGL_STREAM_FIFO_LENGTH_KHR 0x31fc
#define EGL_DRM_CRTC_EXT 0x3234
#define EGL_NO_STREAM_KHR ((EGLStreamKHR) 0)
#define EGL_STREAM_BIT_KHR 0x0800
typedef void* EGLOutputLayerEXT;
typedef void* EGLStreamKHR;
typedef void* EGLDeviceEXT;
typedef EGLBoolean (EGLAPIENTRY * PFNEGLQUERYDEVICESEXTPROC)(EGLint,EGLDeviceEXT*,EGLint*);
typedef const char *(EGLAPIENTRY * PFNEGLQUERYDEVICESTRINGEXTPROC)(EGLDeviceEXT,EGLint);
typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum,void*,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETOUTPUTLAYERSEXTPROC)(EGLDisplay,const EGLAttrib*,EGLOutputLayerEXT*,EGLint,EGLint*);
typedef EGLStreamKHR (EGLAPIENTRY * PFNEGLCREATESTREAMKHRPROC)(EGLDisplay,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSTREAMKHRPROC)(EGLDisplay,EGLStreamKHR);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMEROUTPUTEXTPROC)(EGLDisplay,EGLStreamKHR,EGLOutputLayerEXT);
typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC)(EGLDisplay,EGLConfig,EGLStreamKHR,const EGLint*);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,EGLenum,EGLint);
typedef EGLBoolean (EGLAPIENTRY * PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC)(EGLDisplay,EGLStreamKHR,const EGLAttrib*);
#define eglQueryDevicesEXT _glfw.egldevice.QueryDevicesEXT
#define eglQueryDeviceStringEXT _glfw.egldevice.QueryDeviceStringEXT
#define eglGetPlatformDisplayEXT _glfw.egldevice.GetPlatformDisplayEXT
#define eglGetOutputLayersEXT _glfw.egldevice.GetOutputLayersEXT
#define eglCreateStreamKHR _glfw.egldevice.CreateStreamKHR
#define eglDestroyStreamKHR _glfw.egldevice.DestroyStreamKHR
#define eglStreamConsumerOutputEXT _glfw.egldevice.StreamConsumerOutputEXT
#define eglCreateStreamProducerSurfaceKHR _glfw.egldevice.CreateStreamProducerSurfaceKHR
#define eglStreamAttribKHR _glfw.egldevice.StreamAttribKHR
#define eglStreamConsumerAcquireAttribKHR _glfw.egldevice.StreamConsumerAcquireAttribKHR
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
#define _glfw_dlsym(handle, name) dlsym(handle, name)
#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType)window->egldevice.handle)
#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowEGLDevice egldevice
#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryEGLDevice egldevice
#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorEGLDevice egldevice
#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorEGLDevice egldevice
#define _GLFW_PLATFORM_CONTEXT_STATE
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// EGLDevice-specific per-window data
//
typedef struct _GLFWwindowEGLDevice
{
int xsurfsize, ysurfsize;
int xoffset, yoffset;
int fifo;
uint32_t planeId;
EGLDisplay handle;
EGLOutputLayerEXT eglLayer;
EGLStreamKHR eglStream;
} _GLFWwindowEGLDevice;
// EGLDevice-specific global data
//
typedef struct _GLFWlibraryEGLDevice
{
int drmFd;
PFNEGLQUERYDEVICESEXTPROC QueryDevicesEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC QueryDeviceStringEXT;
PFNEGLGETPLATFORMDISPLAYEXTPROC GetPlatformDisplayEXT;
PFNEGLGETOUTPUTLAYERSEXTPROC GetOutputLayersEXT;
PFNEGLCREATESTREAMKHRPROC CreateStreamKHR;
PFNEGLDESTROYSTREAMKHRPROC DestroyStreamKHR;
PFNEGLSTREAMCONSUMEROUTPUTEXTPROC StreamConsumerOutputEXT;
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC CreateStreamProducerSurfaceKHR;
PFNEGLSTREAMATTRIBKHRPROC StreamAttribKHR;
PFNEGLSTREAMCONSUMERACQUIREATTRIBKHRPROC StreamConsumerAcquireAttribKHR;
} _GLFWlibraryEGLDevice;
// EGLDevice-specific per-monitor data
//
typedef struct _GLFWmonitorEGLDevice
{
int crtcIndex;
uint32_t connId, encId, crtcId;
} _GLFWmonitorEGLDevice;
// EGLDevice-specific per-cursor data
//
typedef struct _GLFWcursorEGLDevice
{
} _GLFWcursorEGLDevice;
void _glfwPollMonitorsEGLDevice(void);

430
src/egldevice_window.c Normal file
View File

@ -0,0 +1,430 @@
//========================================================================
// GLFW 3.3 EGLDevice - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
///////////////////////////////////////////////////////////////////////////
//////// GLFW platform API /////////////
///////////////////////////////////////////////////////////////////////////
int _glfwPlatformCreateWindow(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
int n;
_GLFWmonitor* monitor;
EGLAttrib layerAttribs[] = { EGL_NONE, EGL_NONE, EGL_NONE };
EGLint streamAttribs[] = { EGL_STREAM_FIFO_LENGTH_KHR,
window->egldevice.fifo, EGL_NONE };
EGLint surfaceAttribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_NONE };
if (window->monitor)
monitor = window->monitor;
else
monitor = _glfw.monitors[0];
window->egldevice.xsurfsize = wndconfig->width;
window->egldevice.ysurfsize = wndconfig->height;
if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
return GLFW_FALSE;
// Get the layer for this crtc/plane
layerAttribs[0] = EGL_DRM_CRTC_EXT;
layerAttribs[1] = (EGLAttrib)monitor->egldevice.crtcId;
if (!eglGetOutputLayersEXT(_glfw.egl.display, layerAttribs,
&window->egldevice.eglLayer,
1, &n) || !n)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to obtain EGLOutputLayer");
return GLFW_FALSE;
}
// Create a stream and connect to the output
window->egldevice.eglStream =
eglCreateStreamKHR(_glfw.egl.display, streamAttribs);
if (window->egldevice.eglStream == EGL_NO_STREAM_KHR)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to create stream (error 0x%x)",
eglGetError());
return GLFW_FALSE;
}
if (!eglStreamConsumerOutputEXT(_glfw.egl.display,
window->egldevice.eglStream,
window->egldevice.eglLayer))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to connect stream (error 0x%x)",
eglGetError());
return GLFW_FALSE;
}
// Create a surface to feed the stream
surfaceAttribs[1] = window->egldevice.xsurfsize;
surfaceAttribs[3] = window->egldevice.ysurfsize;
window->context.egl.surface =
eglCreateStreamProducerSurfaceKHR(_glfw.egl.display,
window->context.egl.config,
window->egldevice.eglStream,
surfaceAttribs);
if (window->context.egl.surface == EGL_NO_SURFACE)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Unable to create rendering surface (error 0x%x)", eglGetError());
return GLFW_FALSE;
}
return GLFW_TRUE;
}
void _glfwPlatformDestroyWindow(_GLFWwindow* window)
{
if (window->context.client != GLFW_NO_API)
window->context.destroy(window);
if (window->egldevice.eglStream != EGL_NO_STREAM_KHR)
eglDestroyStreamKHR(_glfw.egl.display, window->egldevice.eglStream);
}
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowTitle is not supported");
}
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowIcon is not supported");
}
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
{
if (xpos)
*xpos = window->egldevice.xoffset;
if (ypos)
*ypos = window->egldevice.yoffset;
}
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
{
window->egldevice.xoffset = xpos;
window->egldevice.yoffset = ypos;
drmModeRes* res_info;
_GLFWmonitor* monitor;
if (window->monitor)
monitor = window->monitor;
else
monitor = _glfw.monitors[0];
res_info = drmModeGetResources(_glfw.egldevice.drmFd);
if (drmModeSetCrtc(_glfw.egldevice.drmFd,
res_info->crtcs[monitor->egldevice.crtcIndex],
-1, window->egldevice.xoffset, window->egldevice.yoffset,
&res_info->connectors[monitor->egldevice.crtcIndex], 1, NULL))
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: Setting window pos failed");
}
drmModeFreeResources(res_info);
}
void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->egldevice.xsurfsize;
if (height)
*height = window->egldevice.ysurfsize;
}
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowSize not implemented");
}
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowSizeLimits not implemented");
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowAspectRatio not implemented");
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
{
_glfwPlatformGetWindowSize(window, width, height);
}
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetWindowFrameSize not implemented");
}
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformIconifyWindow not implemented");
}
void _glfwPlatformRestoreWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformRestoreWindow not implemented");
}
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformMaximizeWindow not implemented");
}
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowResizable not implemented");
}
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowDecorated not implemented");
}
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowFloating not implemented");
}
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformRequestWindowAttention not implemented");
}
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
return;
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformUnhideWindow not implemented");
}
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformHideWindow not implemented");
}
void _glfwPlatformFocusWindow(_GLFWwindow* window)
{
return;
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetWindowMonitor not implemented");
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowFocused not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowIconified(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowIconified not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowVisible(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowVisible not implemented");
return GLFW_FALSE;
}
int _glfwPlatformWindowMaximized(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWindowMaximized not implemented");
return 0;
}
void _glfwPlatformPollEvents(void)
{
_glfwDetectJoystickConnectionLinux();
}
void _glfwPlatformWaitEvents(void)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWaitEvents not supported");
}
void _glfwPlatformWaitEventsTimeout(double timeout)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformWaitEventsTimeout not supported");
}
void _glfwPlatformPostEmptyEvent(void)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformPostEmptyEvent not supported");
}
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetCursorPos not supported");
}
void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursorPos not supported");
}
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursorMode not supported");
}
const char* _glfwPlatformGetKeyName(int key, int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetKeyName not supported");
return NULL;
}
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateCursor not supported");
return GLFW_FALSE;
}
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateStandardCursor not supported");
return GLFW_FALSE;
}
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
return;
}
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetCursor not supported");
}
void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformSetClipboardString not supported");
}
const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetClipboardString not supported");
return NULL;
}
const char* _glfwPlatformGetScancodeName(int scancode)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetScancodeName not supported");
return "";
}
int _glfwPlatformGetKeyScancode(int key)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetKeyScancode not supported");
return -1;
}
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetRequiredInstanceExtensions not supported");
}
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformGetPhysicalDevicePresentationSupport not supported");
return GLFW_FALSE;
}
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"EGLDevice: _glfwPlatformCreateWindowSurface not supported");
return VK_ERROR_INITIALIZATION_FAILED;
}

View File

@ -46,6 +46,8 @@
#cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for OSMesa
#cmakedefine _GLFW_OSMESA
// Define this to 1 if building GLFW for EGLDevice
#cmakedefine _GLFW_EGLDEVICE
// Define this to 1 if building as a shared library / dynamic library / DLL
#cmakedefine _GLFW_BUILD_DLL

View File

@ -190,6 +190,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
#include "mir_platform.h"
#elif defined(_GLFW_OSMESA)
#include "null_platform.h"
#elif defined(_GLFW_EGLDEVICE)
#include "egldevice_platform.h"
#else
#error "No supported window creation API selected"
#endif