egl: implement callbacks for defining custom EGL attributes
Depending on the underlying EGL library, it may be desirable to conditionally set some specific EGL attributes depending on available extensions and other application state. SDL's EGL usage makes this a little bit complicated because: - there are multiple functions used to set up a working EGL context - some of these functions take different types of EGL attributes (EGLAttrib vs EGLint) - the EGL extension list before creating an EGLDisplay differs from the extension list after (i.e. display vs client extensions) - all of the above happens in a single SDL_CreateWindow call This leaves no place for the application to discover what EGL extensions are available and provide custom attribute lists. Until now, if a developer wants to add a custom EGL attribute for eglGetPlatformDisplay, eglCreateWindowSurface or eglCreateContext, they needed to patch SDL itself. This is very undesirable, since such developers would have to disable the SDL dynapi in order to maintain compatibility with their needs. This patch implements some callbacks which developers can use to dynamically generate custom EGL attributes for SDL to use during SDL_CreateWindow.main
parent
0644042eb8
commit
085a276d6c
|
@ -223,6 +223,14 @@ typedef void *SDL_GLContext;
|
|||
typedef void *SDL_EGLDisplay;
|
||||
typedef void *SDL_EGLConfig;
|
||||
typedef void *SDL_EGLSurface;
|
||||
typedef intptr_t SDL_EGLAttrib;
|
||||
typedef int SDL_EGLint;
|
||||
|
||||
/**
|
||||
* \brief EGL attribute initialization callback types.
|
||||
*/
|
||||
typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void);
|
||||
typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void);
|
||||
|
||||
/**
|
||||
* \brief OpenGL configuration attributes
|
||||
|
@ -2089,6 +2097,30 @@ extern DECLSPEC SDL_EGLConfig SDLCALL SDL_EGL_GetCurrentEGLConfig(void);
|
|||
*/
|
||||
extern DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowEGLSurface(SDL_Window * window);
|
||||
|
||||
/**
|
||||
* Sets the callbacks for defining custom EGLAttrib arrays for EGL
|
||||
* initialization.
|
||||
*
|
||||
* Each callback should return a pointer to an EGL attribute array terminated
|
||||
* with EGL_NONE. Callbacks may return NULL pointers to signal an error, which
|
||||
* will cause the SDL_CreateWindow process to fail gracefully.
|
||||
*
|
||||
* The arrays returned by each callback will be appended to the existing
|
||||
* attribute arrays defined by SDL.
|
||||
*
|
||||
* NOTE: These callback pointers will be reset after SDL_GL_ResetAttributes.
|
||||
*
|
||||
* \param platformAttribCallback Callback for attributes to pass to
|
||||
* eglGetPlatformDisplay.
|
||||
* \param surfaceAttribCallback Callback for attributes to pass to
|
||||
* eglCreateSurface.
|
||||
* \param contextAttribCallback Callback for attributes to pass to
|
||||
* eglCreateContext.
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback,
|
||||
SDL_EGLIntArrayCallback surfaceAttribCallback,
|
||||
SDL_EGLIntArrayCallback contextAttribCallback);
|
||||
|
||||
/**
|
||||
* Get the size of a window's underlying drawable in pixels.
|
||||
*
|
||||
|
|
|
@ -514,7 +514,16 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa
|
|||
}
|
||||
|
||||
if (_this->egl_data->eglGetPlatformDisplay) {
|
||||
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, NULL);
|
||||
EGLAttrib *attribs = NULL;
|
||||
if (_this->egl_platformattrib_callback) {
|
||||
attribs = _this->egl_platformattrib_callback();
|
||||
if (!attribs) {
|
||||
_this->gl_config.driver_loaded = 0;
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
return SDL_SetError("EGL platform attribute callback returned NULL pointer");
|
||||
}
|
||||
}
|
||||
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, attribs);
|
||||
} else {
|
||||
if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
|
||||
_this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddressInternal(_this, "eglGetPlatformDisplayEXT");
|
||||
|
@ -934,8 +943,8 @@ SDL_EGL_ChooseConfig(_THIS)
|
|||
SDL_GLContext
|
||||
SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
|
||||
{
|
||||
/* max 14 values plus terminator. */
|
||||
EGLint attribs[15];
|
||||
/* max 16 key+value pairs plus terminator. */
|
||||
EGLint attribs[33];
|
||||
int attr = 0;
|
||||
|
||||
EGLContext egl_context, share_context = EGL_NO_CONTEXT;
|
||||
|
@ -1024,6 +1033,29 @@ SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (_this->egl_contextattrib_callback) {
|
||||
const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]);
|
||||
EGLint *userAttribs, *userAttribP;
|
||||
userAttribs = _this->egl_contextattrib_callback();
|
||||
if (!userAttribs) {
|
||||
_this->gl_config.driver_loaded = 0;
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
SDL_SetError("EGL context attribute callback returned NULL pointer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (userAttribP = userAttribs; *userAttribP != EGL_NONE; ) {
|
||||
if (attr + 3 >= maxAttribs) {
|
||||
_this->gl_config.driver_loaded = 0;
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
SDL_SetError("EGL context attribute callback returned too many attributes");
|
||||
return NULL;
|
||||
}
|
||||
attribs[attr++] = *userAttribP++;
|
||||
attribs[attr++] = *userAttribP++;
|
||||
}
|
||||
}
|
||||
|
||||
attribs[attr++] = EGL_NONE;
|
||||
|
||||
/* Bind the API */
|
||||
|
@ -1190,8 +1222,8 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
|
|||
EGLint format_wanted;
|
||||
EGLint format_got;
|
||||
#endif
|
||||
/* max 2 key+value pairs, plus terminator. */
|
||||
EGLint attribs[5];
|
||||
/* max 16 key+value pairs, plus terminator. */
|
||||
EGLint attribs[33];
|
||||
int attr = 0;
|
||||
|
||||
EGLSurface * surface;
|
||||
|
@ -1232,6 +1264,29 @@ SDL_EGL_CreateSurface(_THIS, NativeWindowType nw)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (_this->egl_surfaceattrib_callback) {
|
||||
const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]);
|
||||
EGLint *userAttribs, *userAttribP;
|
||||
userAttribs = _this->egl_surfaceattrib_callback();
|
||||
if (!userAttribs) {
|
||||
_this->gl_config.driver_loaded = 0;
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
SDL_SetError("EGL surface attribute callback returned NULL pointer");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
for (userAttribP = userAttribs; *userAttribP != EGL_NONE; ) {
|
||||
if (attr + 3 >= maxAttribs) {
|
||||
_this->gl_config.driver_loaded = 0;
|
||||
*_this->gl_config.driver_path = '\0';
|
||||
SDL_SetError("EGL surface attribute callback returned too many attributes");
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
attribs[attr++] = *userAttribP++;
|
||||
attribs[attr++] = *userAttribP++;
|
||||
}
|
||||
}
|
||||
|
||||
attribs[attr++] = EGL_NONE;
|
||||
|
||||
surface = _this->egl_data->eglCreateWindowSurface(
|
||||
|
|
|
@ -398,6 +398,10 @@ struct SDL_VideoDevice
|
|||
void *dll_handle;
|
||||
} gl_config;
|
||||
|
||||
SDL_EGLAttribArrayCallback egl_platformattrib_callback;
|
||||
SDL_EGLIntArrayCallback egl_surfaceattrib_callback;
|
||||
SDL_EGLIntArrayCallback egl_contextattrib_callback;
|
||||
|
||||
/* * * */
|
||||
/* Cache current GL context; don't call the OS when it hasn't changed. */
|
||||
/* We have the global pointers here so Cocoa continues to work the way
|
||||
|
|
|
@ -3646,6 +3646,18 @@ SDL_GL_DeduceMaxSupportedESProfile(int* major, int* minor)
|
|||
#endif
|
||||
}
|
||||
|
||||
void SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback,
|
||||
SDL_EGLIntArrayCallback surfaceAttribCallback,
|
||||
SDL_EGLIntArrayCallback contextAttribCallback)
|
||||
{
|
||||
if (!_this) {
|
||||
return;
|
||||
}
|
||||
_this->egl_platformattrib_callback = platformAttribCallback;
|
||||
_this->egl_surfaceattrib_callback = surfaceAttribCallback;
|
||||
_this->egl_contextattrib_callback = contextAttribCallback;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_GL_ResetAttributes()
|
||||
{
|
||||
|
@ -3653,6 +3665,10 @@ SDL_GL_ResetAttributes()
|
|||
return;
|
||||
}
|
||||
|
||||
_this->egl_platformattrib_callback = NULL;
|
||||
_this->egl_surfaceattrib_callback = NULL;
|
||||
_this->egl_contextattrib_callback = NULL;
|
||||
|
||||
_this->gl_config.red_size = 3;
|
||||
_this->gl_config.green_size = 3;
|
||||
_this->gl_config.blue_size = 2;
|
||||
|
|
Loading…
Reference in New Issue