From 87357e403614a732296f0c60110946db4ef043c5 Mon Sep 17 00:00:00 2001 From: rpm-build Date: Aug 05 2020 11:12:04 +0000 Subject: eglexternalplatform-1.1 base --- diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..252057b --- /dev/null +++ b/COPYING @@ -0,0 +1,19 @@ + Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + + 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, sublicense, + 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 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 NONINFRINGEMENT. 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c8b6828 --- /dev/null +++ b/README.md @@ -0,0 +1,294 @@ +EGL External Platform Interface +=============================== + +Overview +-------- + +This is a work-in-progress specification of the EGL External Platform interface +for writing EGL platforms and their interactions with modern window systems on +top of existing low-level EGL platform implementations. This keeps window system +implementation specifics out of EGL drivers by using application-facing EGL +functions. + +Examples of low-level EGL platforms are `EGL_EXT_platform_device` or +`EGL_KHR_platform_gbm`. + + +Installing the interface +------------------------ + +This is a headers-only specification of the interface. + +To install the interface, just copy the header files under a certain system +headers directory (e.g. /usr/include). + +A template *eglexternalplatform.pc* **pkg-config** is provided along with the +header files. It can be edited to match the location of the header files and +copied to an appropriate **pkg-config** configuration directory (e.g. +/usr/share/pkgconfig). + + +Definitions +----------- + +The following terms are used throughout this README file: + + * *EGL driver* + + An implementation of the full EGL API, either as a vendor library loaded by + GLVND, or as a standalone library linked against by applications. + + * *EGL platform* + + A rendering system an EGL driver can support at runtime. An EGL platform may + refer to a window system (e.g. X11, Wayland) or a headless rendering platform + (e.g. EGLDevice, GBM). + + See section *2.1 "Native Platforms and Rendering APIs"* of the EGL 1.5 + specification, or *EGL_EXT_platform_base* extension. + + * *EGL platform library* + + An implementation of a single EGL External Platform interface on top of + interfaces provided by an EGL driver. + + * *EGL entrypoint layer* + + Thin layer sitting on top of an EGL driver internal implementation that will + dispatch calls coming from applications (or GLVND) to either an EGL platform + library or the EGL driver itself. + + * *EGL External Platform interface* + + Set of functions, hooks, and data structures definitions an EGL entrypoint + layer will use to interact with EGL platform libraries. + + * *EGL external & internal object handle* + + An external object handle refers to the EGL object handle given to the + application. These may be provided by either an EGL platform library or the + EGL driver, depending on what platform the object belongs to. + + In turn, an internal object handle refers to the EGL object handle that only + the EGL driver internal implementation understands. + + +Interface walk-through +---------------------- + +All functions and hooks of an EGL platform library are made available either as +an exports table or dynamically loaded hooks to the EGL entrypoint layer. A +special entry point `loadEGLExternalPlatform()` function must be used to load +all exports and data of a given EGL platform library. + +`loadEGLExternalPlatform()` takes *major* and *minor* numbers corresponding to +the version of the EGL External Platform interface the EGL entrypoint layer will +use to interact with the loaded platform. This provides a means for both the +interface and EGL platform libraries to evolve separately in a backwards +compatible way. + +Different types of functions and hooks are defined and described below. Unless +otherwise specified, the following functions are made available as an exports +table to the EGL entrypoint layer: + + * *Pure EGL hooks* + + They are intended to be used in replacement of application-facing EGL + functions. Pure EGL hooks are not provided as entries of the external exports + table, but are retrieved dynamically with the 'getHookAddress()' export. An + EGL platform library can provide a hook for most of the application-facing + functions the EGL entrypoint layer is aware of. + + Examples of these are, among others, hooks for + `eglCreatePlatformWindowSurface()` or `eglSwapBuffers()`. + + * *Derivatives of EGL functions* + + These are variations of application-facing EGL functions that may require + extra parameters or will have a sligthly different behavior in order to help + the EGL entrypoint layer operate in presence of EGL platform libraries. + + An example of these is `queryString()` which is symmetric to + `eglQueryString()`, but a new EGLExtPlatformString enum is given for the + string name instead. It helps `eglQueryString()` to return the appropriate + extension string depending on what EGL platform libraries are available, for + instance. + + * *External object validation functions* + + The goal of this type of function is to help the EGL entrypoint layer to + determine which EGL platform library should handle which calls when opaque + native resources are given. + + An example of these functions is `isValidNativeDisplay()`, which helps + `eglGetDisplay()`. + + * *External -> Internal object translation functions* + + Whenever non-externally implemented EGL functions are called, translation + from external (EGL platform library) object handles to internal (EGL driver) + ones is required. + + `getInternalHandle()` returns the EGL internal handle of a given external + object. + + * *Callbacks* + + Sometimes, there might be operations that require execution of + non-application-facing code within the EGL platform library. The EGL External + Platform interface provides a means for registering callbacks in such cases. + + Unlike the previously described functions, which are implemented by an EGL + platform library and made available to the EGL entrypoint layer, these + callbacks allow the latter to register EGL driver functions with the former. + + An example of these is the `eglSetError()` callback that allows EGL platform + libraries to set EGL error codes to be queried by the application in case of + failure. + +More detailed information of every symbol the EGL External Platform interface +defines can be found in the `interface/eglexternalplatform.h` file. + + +Interactions with the EGL driver +-------------------------------- + +Discovery and registration of EGL platform libraries is the EGL entrypoint +layer's responsibility. What discovery method to use is specific to each +implementation, but it is advisable to use something portable and fully +configurable (see JSON-based vendor libraries loader in GLVND). + +The initial interaction of an EGL entrypoint layer with an EGL platform library +happens with `loadEGLExternalPlatform()`. This function allows to retrieve both +the exports table and data such as the platform enumeration value. It also +provides a means for the EGL entrypoint layer to pass in an EGL driver imports +structure such that EGL platform libraries can fetch any driver methods they may +require to use. + +`loadEGLExternalPlatform()` takes *major* and *minor* numbers corresponding to +the version of the EGL External Platform interface the EGL entrypoint layer will +use. The EGL platform library must then check those numbers against the +interface version it implements, and return the appropriate exports and data +(or fail if versions are not compatible). + +EGL platform libraries may initialize their own private platform data +structure at load time to be given to the EGL entrypoint layer. The EGL +entrypoint layer will in turn pass the structure to all export and hook +functions which take another platform's EGLDisplay, or which do not take an +EGLDisplay as input (client extensions). + +All EGLDisplay creation operations will be forwarded to the EGL platform library +`getPlatformDisplay()` export. This gives the EGL entrypoint layer the ability +to track which EGLDisplay belongs to which platform in order to dispatch +subsequent functions. + +All EGLSurface creation operations will also be forwarded to the appropriate EGL +platform library hooks. They are required to be externally implemented for +applications to be able to present buffers onto a surface. + +Any other EGL object creation operation can be also hooked, but the internal +handle must be always returned. + +Note that, by design, all object creation operations must be hooked for objects +that are currently required to be externally backed (EGLDisplay and EGLSurface). + +Some functions need to be handled by a particular EGL platform library, but +either do not take an EGLDisplay handle or take an EGLDisplay handle that +belongs to a different platform. These functions will require special handling, +which will be defined on a case-by-case basis. For example, `eglGetDisplay()` +uses the `isValidNativeDisplay()` export in order to determine what EGL platform +library to use, and then the `getPlatformDisplay()` export to actually create +the display. + +The following diagram illustrates the control flow between an application, +the EGL driver, and two different EGL platform libraries: + + +-------------------------------+ + | | + | Application | + | | + +--------------+----------------+ + | + | + +--------------|----------------+ + | | | +------------------------+ + | EGL driver | | | | + | | | +----> EGL platform library A +-----+ + | +-----------v-------------+ | | | | | + | | | | | +------------------------+ | + | | EGL entrypoint layer +-----+ | + | | | | | +------------------------+ | + | +-----------+-------------+ | | | | | + | | | +----> EGL platform library B +--+ | + | | | | | | | + | +-----------v-------------+ | +------------------------+ | | + | | | | | | + | | | | | | + | | <--------------------------------------+ | + | | EGL driver internal | | | + | | | | | + | | <-----------------------------------------+ + | | | | + | +-------------------------+ | + | | + +-------------------------------+ + + +Sample code +----------- + +In order to illustrate how to use the EGL External Platform interface, a few +files with sample code can be found under the 'samples' folder: + + * 'samples/sample-egl-server.c': + + Sample code for a display server working on top of the EGLStream family of + extensions. + + * 'samples/sample-egl-client.c': + + Sample code for an EGL application that would run on Foo window system. + + * 'samples/libsample-egl-platform.c': + + Sample code for an EGL External Platform implementation that would add + EGL_PLATFORM_SAMPLE support on top of EGLStream family of extensions. + +Note that these source files are incomplete, and are not intended to be used +as-is. + +Also, the NVIDIA Wayland implementation can be found at: + +https://github.com/NVIDIA/egl-wayland + + +Acknowledgements +---------------- + +Thanks to James Jones for the original implementation of the Wayland external +platform that led to the design of the EGL External Platform infrastructure. + + +### EGL External Platform interface ### + +The EGL External Platform interface itself is licensed as follows: + + Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + + 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, sublicense, + 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 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 NONINFRINGEMENT. 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. diff --git a/eglexternalplatform.pc b/eglexternalplatform.pc new file mode 100644 index 0000000..123692e --- /dev/null +++ b/eglexternalplatform.pc @@ -0,0 +1,6 @@ +includedir=/usr/include/EGL + +Name: EGL External Platform interface +Description: EGL External Platform interface +Version: 1.1 +Cflags: -I${includedir} diff --git a/interface/eglexternalplatform.h b/interface/eglexternalplatform.h new file mode 100644 index 0000000..8d8559d --- /dev/null +++ b/interface/eglexternalplatform.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. 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 EGL_EXTERNAL_PLATFORM_H +#define EGL_EXTERNAL_PLATFORM_H + +#include +#include +#include "eglexternalplatformversion.h" + +/* EGL external platform interface objects */ +typedef struct EGLExtPlatformExports EGLExtPlatformExports; +typedef struct EGLExtPlatform EGLExtPlatform; +typedef struct EGLExtDriver EGLExtDriver; + +/* EGLExtPlatformString enum. This indicates what string to query through + * queryString() */ +typedef enum { + /* + * Platform client extensions + * + * Returns a extension string including the specific platform client + * extensions. E.g. EGL_EXT_platform_wayland on Wayland platform. + * + * The parameter is EGL_NO_DISPLAY. + */ + EGL_EXT_PLATFORM_PLATFORM_CLIENT_EXTENSIONS = 0, + + /* + * Display extensions + * + * Returns a extension string including all display extensions supported on + * the given display by the external platform implementation. + */ + EGL_EXT_PLATFORM_DISPLAY_EXTENSIONS, + + EGL_EXT_PLATFORM_STRING_NAME_COUNT +} EGLExtPlatformString; + + +/* + * loadEGLExternalPlatform() + * + * Loads the EGL external platform and returns a EGLExtPlatform object where + * external platform data and exported functions have been properly set + * according to the given major and minor version numbers + * + * If a compatible external platform is found for ., EGL_TRUE is + * returned and is properly initialized. Otherwise, EGL_FALSE is + * returned and remains unchanged + * + * A reference to the underlying EGL implementation that must be used is passed + * in . + */ +typedef EGLBoolean (*PEGLEXTFNLOADEGLEXTERNALPLATFORM) (int major, int minor, const EGLExtDriver *driver, EGLExtPlatform *platform); + +/* + * unloadEGLExternalPlatform() + * + * Unloads the EGL external platform, freeing any resources associated to the + * given platform data structure that may have been allocated and not yet freed. + * + * If all resources are properly freed, EGL_TRUE is returned and the given + * platform data pointer becomes invalid. Otherwise, EGL_FALSE is returned. + */ +typedef EGLBoolean (*PEGLEXTFNUNLOADEGLEXTERNALPLATFORM) (void *platformData); + +/* + * getHookAddress() + * + * The EGL external platform interface defines a minimum set of functions that + * must be provided by any EGL external platform at loadEGLExternalPlatform() + * time. + * + * However, most of the other EGL functions can be overwritten by an EGL + * external platform. + * + * The EGL implementation will call into getHookAddress() to retrieve any + * additional EGL function that the external platform may implement. Its + * behavior is comparable to eglGetProcAddress(). + * + * Returns the hook address if the given functions is implemented; otherwise, + * returns NULL. + */ +typedef void* (*PEGLEXTFNGETHOOKADDRESS) (void *platformData, const char *name); + +/* + * isValidNativeDisplay() + * + * Validity check function for a native display. It will return EGL_TRUE if the + * given native display is valid and belongs to the external platform + * implementation; otherwise, it will return EGL_FALSE. + */ +typedef EGLBoolean (*PEGLEXTFNISVALIDNATIVEDISPLAY) (void *platformData, void *nativeDisplay); + +/* + * getPlatformDisplay() + * + * Same as eglGetPlatformDisplay() + */ +typedef EGLDisplay (*PEGLEXTFNGETPLATFORMDISPLAY) (void *platformData, EGLenum platform, void *nativeDisplay, const EGLAttrib* attribs); + +/* + * queryString() + * + * Similar to eglQueryString(), but takes its own enumeration as the string name + * parameter. + * + * Returns the appropriate extension string which is supported by the external + * platform. See descriptions of EGLExtPlatformString enums for more details. + */ +typedef const char * (*PEGLEXTFNQUERYSTRING) (void *platformData, EGLDisplay dpy, EGLExtPlatformString name); + +/* + * getInternalHandle() + * + * Conversion function from an EGL external object handle to its corresponding + * EGL internal one. It will return the internal EGL object handle if the given + * external handle is valid and belongs to the given EGLDisplay; otherwise, it + * will return NULL. + * + * Note that the object handle type must be provided by the caller. Its value + * must be one of the object type enums as defined in EGL_KHR_debug. + */ +typedef void* (*PEGLEXTFNGETINTERNALHANDLE) (EGLDisplay dpy, EGLenum type, void *handle); + +/* + * getObjectLabel() + * + * Returns an EGL external object label previously attached with + * eglLabelObjectKHR() from EGL_KHR_debug. + * + * Note that the object handle type must be provided by the caller. Its value + * must be one of the object type enums as defined in EGL_KHR_debug. + */ +typedef void* (*PEGLEXTFNGETOBJECTLABEL) (EGLDisplay dpy, EGLenum type, void *handle); + + +/* + * EGLExtPlatformExports definition. This is the exports table an external + * platform must fill out and make available for the EGL implementation to use + */ +struct EGLExtPlatformExports { + PEGLEXTFNUNLOADEGLEXTERNALPLATFORM unloadEGLExternalPlatform; + PEGLEXTFNGETHOOKADDRESS getHookAddress; + + PEGLEXTFNISVALIDNATIVEDISPLAY isValidNativeDisplay; + PEGLEXTFNGETPLATFORMDISPLAY getPlatformDisplay; + + PEGLEXTFNQUERYSTRING queryString; + + PEGLEXTFNGETINTERNALHANDLE getInternalHandle; + + PEGLEXTFNGETOBJECTLABEL getObjectLabel; +}; + +/* + * EGLExtPlatform definition. This is common to all external platforms + * + * Fields: + * - major/minor: External platform major/minor version number. Specify the EGL + * external platform interface version number the given platform + * implements. They are tied to EGL external platform interface + * changes. + * - micro: External platform micro version number. Similar to + * major/minor numbers, but it is tied to specific external + * platform implementation changes. + * - platform: EGL platform enumeration the corresponding external platform + * implements. + * - data: Opaque pointer to platform specific data. At platform + * load time, the external platform can initialize its own data + * structure to store any information that may be required by + * any function that does not take an EGLDisplay or the display + * belongs to another platform. + * - exports: External platform exports table. + */ +struct EGLExtPlatform { + struct { + int major; + int minor; + int micro; + } version; + EGLenum platform; + void *data; + EGLExtPlatformExports exports; +}; + + +/* + * getProcAddress() + * + * Equivalent to eglGetProcAddress() to fetch EGL methods provided by a + * specific EGL driver. + */ +typedef void* (*PEGLEXTFNGETPROCADDRESS) (const char *name); + +/* + * setError() + * + * Sets the last EGL error, which can be queried with eglGetError() later on. It + * also calls the EGL_KHR_debug callback if such extension is supported by the + * driver. + * + * Takes the EGL error code and both message type and string as defined in + * EGL_KHR_debug for the debug callback function. + */ +typedef void (*PEGLEXTFNSETERROR) (EGLint error, EGLint msgType, const char *msg); + +/* + * debugMessage() + * + * Calls the EGL_KHR_debug callback if such extension is supported by the + * driver. + * + * Takes both message type and string as defined in EGL_KHR_debug for the debug + * callback function. + */ +typedef void* (*PEGLEXTFNDEBUGMESSAGE) (EGLint msgType, const char *msg); + +/* + * streamSwapInterval() + * + * Handle swapinterval on the EGLStream consumer side. Should be a noop for + * any consumer that does not present directly to a display. + * + * Takes the stream handle and a pointer to the interval value as parameters. + * + * Returns one of the following EGL error codes: + * - EGL_SUCCESS: The interval setting operation succeeded (or noop). + * - EGL_BAD_MATCH: A server-side interval override is in place. The override + * value is returned in the parameter. + * - EGL_BAD_ACCESS: The interval setting operation failed. + */ +typedef EGLint (*PEGLEXTFNSTREAMSWAPINTERVAL) (EGLStreamKHR stream, int *interval); + +/* + * EGLExtDriver definition. The EGL external driver is the component in + * charge of dispatching EGL calls to the underlying EGL implementation. + */ +struct EGLExtDriver { + PEGLEXTFNGETPROCADDRESS getProcAddress; + PEGLEXTFNSETERROR setError; + PEGLEXTFNDEBUGMESSAGE debugMessage; + PEGLEXTFNSTREAMSWAPINTERVAL streamSwapInterval; +#if EGL_EXTERNAL_PLATFORM_HAS(DRIVER_VERSION) + int major; + int minor; +#endif +}; + +#endif // EGL_EXTERNAL_PLATFORM_H diff --git a/interface/eglexternalplatformversion.h b/interface/eglexternalplatformversion.h new file mode 100644 index 0000000..d5b22ab --- /dev/null +++ b/interface/eglexternalplatformversion.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. 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 EGL_EXTERNAL_PLATFORM_VERSION_H +#define EGL_EXTERNAL_PLATFORM_VERSION_H + +/* + * . + * defines the EGL external platform interface version. + * + * The includer of this file can override either + * EGL_EXTERNAL_PLATFORM_VERSION_MAJOR or EGL_EXTERNAL_PLATFORM_VERSION_MINOR in + * order to build against a certain EGL external platform interface version. + * + * Note that, if only EGL_EXTERNAL_PLATFORM_VERSION_MAJOR is overridden, the + * least possible value for EGL_EXTERNAL_PLATFORM_VERSION_MINOR is taken. + * + * + * How to update these version numbers: + * + * - If a backwards-compatible change is made to the interface, increase + * EGL_EXTERNAL_PLATFORM_VERSION_MINOR by 1 + * + * - If backwards-compatibility is broken by a change, increase + * EGL_EXTERNAL_PLATFORM_VERSION_MAJOR by 1 and set + * EGL_EXTERNAL_PLATFORM_VERSION_MINOR to 0 (keep these kind of changes to + * the minimum) + */ +#if !defined(EGL_EXTERNAL_PLATFORM_VERSION_MAJOR) + #define EGL_EXTERNAL_PLATFORM_VERSION_MAJOR 1 + #if !defined(EGL_EXTERNAL_PLATFORM_VERSION_MINOR) + #define EGL_EXTERNAL_PLATFORM_VERSION_MINOR 1 + #endif +#elif !defined(EGL_EXTERNAL_PLATFORM_VERSION_MINOR) + #define EGL_EXTERNAL_PLATFORM_VERSION_MINOR 0 +#endif + + +/* + * EGL_EXTERNAL_PLATFORM_VERSION_CMP + * + * Helper macro to compare two different version numbers. It evaluates to true + * if <_MAJOR1_>.<_MINOR1_> is compatible with <_MAJOR2_>.<_MINOR2_> + */ +#define EGL_EXTERNAL_PLATFORM_VERSION_CMP(_MAJOR1_, _MINOR1_, _MAJOR2_, _MINOR2_) \ + (((_MAJOR1_) == (_MAJOR2_)) && ((_MINOR1_) >= (_MINOR2_))) + +/* + * EGL_EXTERNAL_PLATFORM_VERSION_CHECK + * + * Helper macro to check whether the current EGL external platform interface + * version is compatible with the given version number <_MAJOR_>.<_MINOR_> + */ +#define EGL_EXTERNAL_PLATFORM_VERSION_CHECK(_MAJOR_, _MINOR_) \ + EGL_EXTERNAL_PLATFORM_VERSION_CMP(EGL_EXTERNAL_PLATFORM_VERSION_MAJOR, \ + EGL_EXTERNAL_PLATFORM_VERSION_MINOR, \ + _MAJOR_, _MINOR_) + +/* + * EGL_EXTERNAL_PLATFORM_HAS + * + * Helper macro to check whether the current EGL external platform interface + * version implements the given feature <_FEATURE_> + */ +#define EGL_EXTERNAL_PLATFORM_HAS(_FEATURE_) \ + EGL_EXTERNAL_PLATFORM_VERSION_CHECK(EGL_EXTERNAL_PLATFORM_ ## _FEATURE_ ## _SINCE_MAJOR, \ + EGL_EXTERNAL_PLATFORM_ ## _FEATURE_ ## _SINCE_MINOR) + +/* + * EGL_EXTERNAL_PLATFORM_SUPPORTS + * + * Helper macro to check whether the given EGL external platform interface + * version number <_MAJOR_>.<_MINOR_> supports the given feature <_FEATURE_> + */ +#define EGL_EXTERNAL_PLATFORM_SUPPORTS(_MAJOR_, _MINOR_, _FEATURE_) \ + EGL_EXTERNAL_PLATFORM_VERSION_CMP(_MAJOR_, _MINOR_, \ + EGL_EXTERNAL_PLATFORM_ ## _FEATURE_ ## _SINCE_MAJOR, \ + EGL_EXTERNAL_PLATFORM_ ## _FEATURE_ ## _SINCE_MINOR) + +/* + * List of supported features + * + * Whenever a new feature/function is added to the EGL external platform + * interface, along with the corresponding version number bump, a pair of + * . numbers + * must be added. + * + * All new symbols and usages of the new feature/function must be protected with + * EGL_EXTERNAL_PLATFORM_HAS(). + * + * Additionally, any external platform implementation that supports the new + * feature/function, must also protect the corresponding export initialization + * in function 'loadEGLExternalPlatform()' with + * EGL_EXTERNAL_PLATFORM_SUPPORTS(, , ) using the + * given version number. + * + * Example: + * + * In eglexternalplatformversion.h: + * + * #define EGL_EXTERNAL_PLATFORM_FOO_SINCE_MAJOR 1 + * #define EGL_EXTERNAL_PLATFORM_FOO_SINCE_MINOR 0 + * + * In eglexternalplatform.h: + * + * #if EGL_EXTERNAL_PLATFORM_HAS(FOO) + * typedef void* (*PEGLEXTFNFOO)(void *fooAttr); + * #endif + * + * sitruct EGLExtPlatformExports { + * [...] + * + * #if EGL_EXTERNAL_PLATFORM_HAS(FOO) + * PEGLEXTFNFOO foo; + * #endif + * }; + * + * In platform's loadEGLExternalPlatform() implementation: + * + * EGLBoolean loadEGLExternalPlatform(int major, int minor, + * const EGLExtDriver *driver, + * EGLExtPlatform *platform) + * { + * if (!EGL_EXTERNAL_PLATFORM_VERSION_CHECK(major, minor)) { + * return EGL_FALSE; + * } + * + * [...] + * + * #if EGL_EXTERNAL_PLATFORM_HAS(FOO) + * if (EGL_EXTERNAL_PLATFORM_SUPPORTS(major, minor, FOO)) { + * platform->exports.foo = fooImpl; + * } + * #endif + * + * [...] + * } + */ + +/* + * DRIVER_VERSION + * + * and fields added to EGLExtDriver for drivers to let the + * external platform know the supported EGL version + */ +#define EGL_EXTERNAL_PLATFORM_DRIVER_VERSION_SINCE_MAJOR 1 +#define EGL_EXTERNAL_PLATFORM_DRIVER_VERSION_SINCE_MINOR 1 + +#endif // EGL_EXTERNAL_PLATFORM_VERSION_H diff --git a/samples/libsample-egl-platform.c b/samples/libsample-egl-platform.c new file mode 100644 index 0000000..f56d838 --- /dev/null +++ b/samples/libsample-egl-platform.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. 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. + */ + +#define SAMPLE_EXTERNAL_VERSION_MAJOR 1 +#define SAMPLE_EXTERNAL_VERSION_MINOR 0 +#define SAMPLE_EXTERNAL_VERSION_MICRO 123 + +#define EGL_EXTERNAL_PLATFORM_VERSION_MAJOR SAMPLE_EXTERNAL_VERSION_MAJOR +#define EGL_EXTERNAL_PLATFORM_VERSION_MINOR SAMPLE_EXTERNAL_VERSION_MINOR + +#include + + +typedef const char* (*PSAMPLEEGLFNQUERYSTRINGCOREPROC) (EGLDisplay dpy, EGLint name); +typedef EGLBoolean (*PSAMPLEEGLFNINITIALIZECOREPROC) (EGLDisplay dpy, EGLint *major, EGLint *minor); +typedef EGLBoolean (*PSAMPLEEGLFNTERMINATECOREPROC) (EGLDisplay dpy); + +typedef struct SampleDisplay { + sample_display *nativeSampleDpy; + + EGLNativeDisplay nativeEglDpy; /* EGLDevice, GBM device, ... */ + EGLDisplay eglDpy; + + SamplePlatformData *sampleData; +} SampleDisplay; + +typedef struct SampleSurface { + sample_window *nativeSampleWin; + + SampleDisplay *sampleDpy; + + EGLStreamKHR stream; + EGLSurface eglSurf; +} SampleSurface; + +typedef struct SamplePlatformData { + /* Application-facing callbacks fetched from the EGL driver */ + struct { + PSAMPLEEGLFNQUERYSTRINGCOREPROC queryString; + + PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay; + PSAMPLEEGLFNINITIALIZECOREPROC initialize; + PSAMPLEEGLFNTERMINATECOREPROC terminate; + + /* Other EGL functions */ + [...] + } egl; + + /* Non-application-facing callbacks provided by the EGL driver */ + struct { + PEGLEXTFNSETERROR setError; + } callbacks; +} SamplePlatformData; + + +EGLDisplay sampleGetPlatformDisplayExport(void *data, + EGLenum platform, + Void *nativeDpy, + Const EGLAttrib *attribs) +{ + SamplePlatformData *sampleData = (SamplePlatformData *)data; + SampleDisplay *sampleDpy = malloc(sizeof(SampleDisplay)); + + /* Native EGL setup (EGLDevice, GBM device, ...) */ + sampleDpy->nativeSampleDpy = nativeDpy; + sampleDpy->nativeEglDpy = /* Get native EGL display/device */ + + /* Get an EGLDisplay supporting EGLStreams */ + sampleDpy->eglDpy = sampleData->egl.eglGetPlatformDisplayEXT(EGL_PLATFORM_NATIVE, sampleDpy->nativeEglDpy, NULL); + + sampleDpy->sampleData = sampleData; + + /* Rest of the display creation/allocation */ + [...] + + return (EGLDisplay)sampleDpy; +} + +EGLSurface sampleCreatePlatformWindowSurfaceHook(EGLDisplay dpy, + EGLConfig config, + void *nativeWin, + const EGLAttrib *attribs) +{ + SampleDisplay *sampleDpy = (SampleDisplay *)dpy; + SamplePlatformData *sampleData = sampleDpy->sampleData; + SampleSurface *sampleSurf = malloc(sizeof(SampleSurface)); + int fd; + + /* Create the underlying EGLStream */ + sampleSurf->stream = sampleData->egl.eglCreateStreamKHR(sampleDpy->eglDpy, NULL); + + /* Let the server create its EGLStream consumer endpoint */ + fd = sampleData->egl.eglGetStreamFileDescriptorKHR(sampleDpy->eglDpy, sampleSurf->stream); + sample_client_connect(sampleDpy->nativeSampleDpy, fd); + + /* Create a surface producer */ + sampleSurf->nativeSampleWin = nativeWin; + sampleSurf->eglSurf = sampleData->egl.eglCreateStreamProducerSurfaceKHR(sampleDpy->eglDpy, , sampleSurf->stream, NULL); + + /* Rest of the surface creation/allocation */ + [...] + + return (EGLSurface)sampleSurf; +} + +EGLSurface sampleCreatePlatformPixmapSurfaceHook(EGLDisplay dpy, + EGLConfig config, + void *nativePixmap, + const EGLAttrib *attribs) +{ + /* Create pixmap surfae if supported */ + [...] +} + +EGLSurface sampleCreatePbufferSurfaceHook(EGLDisplay dpy, + EGLConfig config, + const EGLint *attribs) +{ + /* Create Pbuffer surfae if supported */ + [...] +} + +EGLBoolean sampleSwapBuffersHook(EGLDisplay dpy, + EGLSurface surface) +{ + SampleDisplay *sampleDpy = (SampleDisplay *)dpy; + SamplePlatformData *sampleData = sampleDpy->sampleData; + SampleSurface *sampleSurf = (SampleSurface *)surface; + + if (sampleSurf->sampleDpy != sampleDpy) { + sampleData->callbacks.setError(EGL_BAD_SURFACE, EGL_DEBUG_MSG_ERROR_KHR, "Invalid surface"); + return EGL_FALSE; + } + + sampleData->egl.eglSwapBuffers(sampleDpy->eglDpy, sampleSurf->eglSurf); + + /* Let the server know a new frame was generated */ + sample_client_repaint(sampleDpy->nativeSampleDpy, sampleSurf->nativeSampleWin->id); + + /* Rest of the swap buffers handling */ + [...] + + return EGL_TRUE; +} + +static struct { + const char name[]; + void *func; +} __sampleHooks[] = { + { "eglCreatePlatformWindowSurface", sampleCreatePlatformWindowSurfaceHook } + { "eglCreatePlatformPixmapSurface", sampleCreatePlatformPixmapSurfaceHook } + { "eglCreatePbufferSurface", sampleCreatePbufferSurfaceHook } + { "eglSwapBuffers", sampleSwapBuffersHook } +}; + +void* sampleGetHookAddressExport(void *data, const char *name) +{ + forall (hook, __sampleHooks) { + if (strcmp(hook->name, name) == 0) { + return hook->func; + } + } + return NULL; +} + +EGLBoolean loadEGLExternalPlatform(int major, int minor, + const EGLExtDriver *driver, + EGLExtPlatform *platform) +{ + SamplePlatformData *sampleData = NULL; + + /* Version checking */ + if (!platform || + !EGL_EXTERNAL_PLATFORM_VERSION_CHECK(major, minor)) { + return EGL_FALSE; + } + + platform->version.major = SAMPLE_EXTERNAL_VERSION_MAJOR; + platform->version.minor = SAMPLE_EXTERNAL_VERSION_MINOR; + platform->version.micro = SAMPLE_EXTERNAL_VERSION_MICRO; + + platform->platform = EGL_PLATFORM_SAMPLE; + + /* Allocate and initialize platform private data */ + sampleData = malloc(sizeof(SamplePlatformData)); + + sampleData->egl.getPlatformDisplay = driver->getProcAddress("eglGetPlatformDisplayEXT") + sampleData->egl.initialize = driver->getProcAddress("eglInitialize") + sampleData->egl.terminate = driver->getProcAddress("eglTerminate") + + sampleData->callbacks.setError = driver->setError; + + /* Rest of imports initialization */ + [...] + + /* Fill with Sample platform data and exports */ + platform->data = (void *)sampleData; + platform->exports.getHookAddress = sampleGetHookAddressExport; + platform->exports.getPlatformDisplay = sampleGetPlatformDisplayExport; + + /* Rest of exports initialization */ + [...] + + return EGL_TRUE; +} diff --git a/samples/sample-egl-client.c b/samples/sample-egl-client.c new file mode 100644 index 0000000..0985b0b --- /dev/null +++ b/samples/sample-egl-client.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. 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. + */ + +int main() { + /* Window system setup */ + __sampleDpy = sample_display_connect("sample-display"); + __sampleSurf = sample_create_surface(__sampleDpy); + + /* Rest of the window system setup */ + [...] + + /* EGL setup */ + __eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_SAMPLE, __sampleDpy, NULL); + __eglSurf = eglCreatePlatformWindowSurfaceEXT(__eglDpy, , __sampleSurf, NULL); + __eglCtx = eglCreateContext(__eglDpy, , EGL_NO_CONTEXT, NULL); + + eglMakeCurrent(__eglDpy, __eglSurf, __eglSurf, __eglCtx); + + /* Rest of the EGL and OpenGL setup */ + [...] + + while (1) { + sample_dispatch_events(__sampleDpy); + + /* Do render */ + [...] + + eglSwapBuffers(__eglDpy, __eglSurf); + } + + /* Cleanup */ + [...] +} diff --git a/samples/sample-egl-server.c b/samples/sample-egl-server.c new file mode 100644 index 0000000..a5b45b8 --- /dev/null +++ b/samples/sample-egl-server.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. 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. + */ + +void handleClientConn(void *data) { + int fd = (int)data; + EGLStreamKHR stream; + GLuint texId; + + stream = eglCreateStreamFromFileDescriptorKHR(__eglDpy, fd); + + glGenTextures(1, &texId); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId); + eglStreamConsumerGLTextureExternalKHR(__eglDpy, stream); + + sampleSurfaceListAppend(__surfaceList, stream, texId); + + /* Rest of the client connection handling */ + [...] +} + +void handleClientRepaint(void *data) { + int id = (int)data; + + forall (surf, __surfaceList) { + if (surf->id == id) { + eglStreamConsumerAcquireKHR(__eglDpy, surf->stream); + break; + } + } + + /* Rest of the client repaint handling */ + [...] +} + +int main() { + /* Window system setup */ + __sampleDpy = sample_create_display("sample-display"); + + sample_listen_to_client_connections(__sampleDpy, handleClientConn); + sample_listen_to_client_repaints(__sampleDpy, handleClientRepaint); + + /* Rest of the window system setup */ + [...] + + /* Native EGL setup (EGLDevice, GBM device, ...) */ + __nativeDpy = /* Get native EGL display/device */ + + /* Get an EGLDisplay supporting EGLStreams that would allow creation of + scanout EGLSurfaces */ + __eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_NATIVE, __nativeDpy, NULL); + eglInitialize(__eglDpy); + + __eglSurf = /* Create a scanout EGLSurface on __eglDpy */; + __eglCtx = eglCreateContext(__eglDpy, , EGL_NO_CONTEXT, NULL); + + eglMakeCurrent(__eglDpy, __eglSurf, __eglSurf, __eglCtx); + + /* Rest of the EGL and OpenGL setup */ + [...] + + while (1) { + sample_dispatch_events(__sampleDpy); + + /* Composite, repaint, ... */ + [...] + + forall (surf, __surfaceList) { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, surf->texId); + /* Draw surface quad */ + } + + /* Rest of the repaint handling */ + [...] + + eglSwapBuffers(__eglDpy, eglSrf); + } + + /* Cleanup */ + [...] +}