video: Improve the EGL attribute callbacks.

Now it has access to information it needs and it's clear who is reponsible
for memory management.

Fixes #11039.
This commit is contained in:
Ryan C. Gordon 2024-10-03 20:09:58 -04:00 committed by Sam Lantinga
parent d4143e02d1
commit 9a5d5a2839
2 changed files with 61 additions and 15 deletions

View file

@ -239,12 +239,60 @@ typedef intptr_t SDL_EGLAttrib;
typedef int SDL_EGLint;
/**
* EGL attribute initialization callback types.
* EGL platform attribute initialization callback.
*
* This is called when SDL is attempting to create an EGL context, to let
* the app add extra attributes to its eglGetPlatformDisplay() call.
*
* The callback should return a pointer to an EGL attribute array terminated
* with `EGL_NONE`. If this function returns NULL, the SDL_CreateWindow
* process will fail gracefully.
*
* The returned pointer should be allocated with SDL_malloc() and will be
* passed to SDL_free().
*
* The arrays returned by each callback will be appended to the existing
* attribute arrays defined by SDL.
*
* \param userdata an app-controlled pointer that is passed to the callback.
* \returns a newly-allocated array of attributes, terminated with `EGL_NONE`.
*
* \since This datatype is available since SDL 3.0.0.
*
* \sa SDL_EGL_SetAttributeCallbacks
*/
typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void *userdata);
typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata);
/**
* EGL surface/context attribute initialization callback types.
*
* This is called when SDL is attempting to create an EGL surface, to let
* the app add extra attributes to its eglCreateWindowSurface() or
* eglCreateContext calls.
*
* For convenience, the EGLDisplay and EGLConfig to use are provided to the
* callback.
*
* The callback should return a pointer to an EGL attribute array terminated
* with `EGL_NONE`. If this function returns NULL, the SDL_CreateWindow
* process will fail gracefully.
*
* The returned pointer should be allocated with SDL_malloc() and will be
* passed to SDL_free().
*
* The arrays returned by each callback will be appended to the existing
* attribute arrays defined by SDL.
*
* \param userdata an app-controlled pointer that is passed to the callback.
* \param display the EGL display to be used.
* \param config the EGL config to be used.
* \returns a newly-allocated array of attributes, terminated with `EGL_NONE`.
*
* \since This datatype is available since SDL 3.0.0.
*
* \sa SDL_EGL_SetAttributeCallbacks
*/
typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata, SDL_EGLDisplay display, SDL_EGLConfig config);
/**
* An enumeration of OpenGL configuration attributes.
@ -2742,28 +2790,23 @@ extern SDL_DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowSurface(SDL_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.
* Callbacks that aren't needed can be set to NULL.
*
* NOTE: These callback pointers will be reset after SDL_GL_ResetAttributes.
*
* \param platformAttribCallback callback for attributes to pass to
* eglGetPlatformDisplay.
* eglGetPlatformDisplay. May be NULL.
* \param surfaceAttribCallback callback for attributes to pass to
* eglCreateSurface.
* eglCreateSurface. May be NULL.
* \param contextAttribCallback callback for attributes to pass to
* eglCreateContext.
* eglCreateContext. May be NULL.
* \param userdata a pointer that is passed to the callbacks.
*
* \since This function is available since SDL 3.0.0.
*/
extern SDL_DECLSPEC void SDLCALL SDL_EGL_SetAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback,
SDL_EGLIntArrayCallback surfaceAttribCallback,
SDL_EGLIntArrayCallback contextAttribCallback, void *userdata);
SDL_EGLIntArrayCallback surfaceAttribCallback,
SDL_EGLIntArrayCallback contextAttribCallback, void *userdata);
/**
* Set the swap interval for the current OpenGL context.

View file

@ -537,6 +537,7 @@ bool SDL_EGL_LoadLibrary(SDL_VideoDevice *_this, const char *egl_path, NativeDis
}
}
_this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplay(platform, (void *)(uintptr_t)native_display, attribs);
SDL_free(attribs);
} else {
if (SDL_EGL_HasExtension(_this, SDL_EGL_CLIENT_EXTENSION, "EGL_EXT_platform_base")) {
_this->egl_data->eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)SDL_EGL_GetProcAddressInternal(_this, "eglGetPlatformDisplayEXT");
@ -1038,7 +1039,7 @@ SDL_GLContext SDL_EGL_CreateContext(SDL_VideoDevice *_this, EGLSurface egl_surfa
if (_this->egl_contextattrib_callback) {
const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]);
EGLint *userAttribs, *userAttribP;
userAttribs = _this->egl_contextattrib_callback(_this->egl_attrib_callback_userdata);
userAttribs = _this->egl_contextattrib_callback(_this->egl_attrib_callback_userdata, _this->egl_data->egl_display, _this->egl_data->egl_config);
if (!userAttribs) {
_this->gl_config.driver_loaded = 0;
*_this->gl_config.driver_path = '\0';
@ -1056,6 +1057,7 @@ SDL_GLContext SDL_EGL_CreateContext(SDL_VideoDevice *_this, EGLSurface egl_surfa
attribs[attr++] = *userAttribP++;
attribs[attr++] = *userAttribP++;
}
SDL_free(userAttribs);
}
attribs[attr++] = EGL_NONE;
@ -1264,7 +1266,7 @@ EGLSurface SDL_EGL_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, Nat
if (_this->egl_surfaceattrib_callback) {
const int maxAttribs = sizeof(attribs) / sizeof(attribs[0]);
EGLint *userAttribs, *userAttribP;
userAttribs = _this->egl_surfaceattrib_callback(_this->egl_attrib_callback_userdata);
userAttribs = _this->egl_surfaceattrib_callback(_this->egl_attrib_callback_userdata, _this->egl_data->egl_display, _this->egl_data->egl_config);
if (!userAttribs) {
_this->gl_config.driver_loaded = 0;
*_this->gl_config.driver_path = '\0';
@ -1282,6 +1284,7 @@ EGLSurface SDL_EGL_CreateSurface(SDL_VideoDevice *_this, SDL_Window *window, Nat
attribs[attr++] = *userAttribP++;
attribs[attr++] = *userAttribP++;
}
SDL_free(userAttribs);
}
attribs[attr++] = EGL_NONE;