/************************************************************/ /** * * @file: egl_surface.cpp * @author: Martin Fouilleul * @date: 17/02/2023 * @revision: * *****************************************************************/ #define EGL_EGLEXT_PROTOTYPES #include "app/app_internal.h" #include "gl_loader.h" #include "graphics_surface.h" #include #include #if OC_PLATFORM_MACOS //NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly #define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE //NOTE: hardcode GLES versions for now //TODO: use version hints, once we have all api versions correctly categorized by glapi.py #define OC_GLES_VERSION_MAJOR 3 #define OC_GLES_VERSION_MINOR 0 #define oc_gl_load_gles oc_gl_load_gles31 #else #define OC_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE #define OC_GLES_VERSION_MAJOR 3 #define OC_GLES_VERSION_MINOR 1 #define oc_gl_load_gles oc_gl_load_gles32 #endif typedef struct oc_egl_surface { oc_surface_data interface; EGLDisplay eglDisplay; EGLConfig eglConfig; EGLContext eglContext; EGLSurface eglSurface; oc_gl_api api; } oc_egl_surface; void oc_egl_surface_destroy(oc_surface_data* interface) { oc_egl_surface* surface = (oc_egl_surface*)interface; if(&surface->api == oc_gl_get_api()) { oc_gl_deselect_api(); } if(eglGetCurrentContext() == surface->eglContext) { eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } eglDestroyContext(surface->eglDisplay, surface->eglContext); eglDestroySurface(surface->eglDisplay, surface->eglSurface); oc_surface_cleanup((oc_surface_data*)surface); free(surface); } void oc_egl_surface_prepare(oc_surface_data* interface) { oc_egl_surface* surface = (oc_egl_surface*)interface; eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext); oc_gl_select_api(&surface->api); } void oc_egl_surface_present(oc_surface_data* interface) { oc_egl_surface* surface = (oc_egl_surface*)interface; eglSwapBuffers(surface->eglDisplay, surface->eglSurface); } void oc_egl_surface_deselect(oc_surface_data* interface) { oc_egl_surface* surface = (oc_egl_surface*)interface; eglMakeCurrent(surface->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); oc_gl_deselect_api(); } void oc_egl_surface_swap_interval(oc_surface_data* interface, int swap) { oc_egl_surface* surface = (oc_egl_surface*)interface; eglSwapInterval(surface->eglDisplay, swap); } void oc_egl_surface_init(oc_egl_surface* surface) { void* nativeLayer = surface->interface.nativeLayer((oc_surface_data*)surface); surface->interface.api = OC_GLES; surface->interface.destroy = oc_egl_surface_destroy; surface->interface.prepare = oc_egl_surface_prepare; surface->interface.present = oc_egl_surface_present; surface->interface.deselect = oc_egl_surface_deselect; surface->interface.swapInterval = oc_egl_surface_swap_interval; EGLAttrib displayAttribs[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, OC_EGL_PLATFORM_ANGLE_TYPE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE, EGL_NONE }; surface->eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, (void*)EGL_DEFAULT_DISPLAY, displayAttribs); eglInitialize(surface->eglDisplay, NULL, NULL); EGLint const configAttributes[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8, EGL_SAMPLE_BUFFERS, 0, EGL_SAMPLES, EGL_DONT_CARE, EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FIXED_EXT, EGL_NONE }; int numConfigs = 0; eglChooseConfig(surface->eglDisplay, configAttributes, &surface->eglConfig, 1, &numConfigs); EGLint const surfaceAttributes[] = { EGL_NONE }; surface->eglSurface = eglCreateWindowSurface(surface->eglDisplay, surface->eglConfig, nativeLayer, surfaceAttributes); eglBindAPI(EGL_OPENGL_ES_API); EGLint contextAttributes[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, OC_GLES_VERSION_MAJOR, EGL_CONTEXT_MINOR_VERSION_KHR, OC_GLES_VERSION_MINOR, EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE, EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE, EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_FALSE, EGL_NONE }; surface->eglContext = eglCreateContext(surface->eglDisplay, surface->eglConfig, EGL_NO_CONTEXT, contextAttributes); eglMakeCurrent(surface->eglDisplay, surface->eglSurface, surface->eglSurface, surface->eglContext); oc_gl_load_gles(&surface->api, (oc_gl_load_proc)eglGetProcAddress); eglSwapInterval(surface->eglDisplay, 1); } oc_surface_data* oc_egl_surface_create_for_window(oc_window window) { oc_egl_surface* surface = 0; oc_window_data* windowData = oc_window_ptr_from_handle(window); if(windowData) { surface = oc_malloc_type(oc_egl_surface); if(surface) { memset(surface, 0, sizeof(oc_egl_surface)); oc_surface_init_for_window((oc_surface_data*)surface, windowData); oc_egl_surface_init(surface); } } return ((oc_surface_data*)surface); }