| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "flutter/testing/test_gl_context.h" | |
| #include <EGL/egl.h> | |
| #include <EGL/eglext.h> | |
| #include <EGL/eglplatform.h> | |
| #include <cstring> | |
| #include "flutter/fml/logging.h" | |
| #include "flutter/testing/test_gl_utils.h" | |
| namespace flutter::testing { | |
| namespace { | |
| bool HasExtension(const char* extensions, const char* name) { | |
| const char* r = strstr(extensions, name); | |
| auto len = strlen(name); | |
| // check that the extension name is terminated by space or null terminator | |
| return r != nullptr && (r[len] == ' ' || r[len] == 0); | |
| } | |
| void CheckSwanglekExtensions() { | |
| const char* extensions = ::eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); | |
| FML_CHECK(HasExtension(extensions, "EGL_EXT_platform_base")) << extensions; | |
| FML_CHECK(HasExtension(extensions, "EGL_ANGLE_platform_angle_vulkan")) | |
| << extensions; | |
| FML_CHECK(HasExtension(extensions, | |
| "EGL_ANGLE_platform_angle_device_type_swiftshader")) | |
| << extensions; | |
| } | |
| EGLDisplay CreateSwangleDisplay() { | |
| CheckSwanglekExtensions(); | |
| PFNEGLGETPLATFORMDISPLAYEXTPROC egl_get_platform_display_EXT = | |
| reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>( | |
| eglGetProcAddress("eglGetPlatformDisplayEXT")); | |
| FML_CHECK(egl_get_platform_display_EXT) | |
| << "eglGetPlatformDisplayEXT not available."; | |
| const EGLint display_config[] = { | |
| EGL_PLATFORM_ANGLE_TYPE_ANGLE, | |
| EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, | |
| EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, | |
| EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE, | |
| EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, | |
| EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE, | |
| EGL_NONE, | |
| }; | |
| return egl_get_platform_display_EXT( | |
| EGL_PLATFORM_ANGLE_ANGLE, | |
| reinterpret_cast<EGLNativeDisplayType*>(EGL_DEFAULT_DISPLAY), | |
| display_config); | |
| } | |
| } // namespace | |
| TestEGLContext::TestEGLContext() { | |
| display = CreateSwangleDisplay(); | |
| FML_CHECK(display != EGL_NO_DISPLAY); | |
| auto result = ::eglInitialize(display, nullptr, nullptr); | |
| FML_CHECK(result == EGL_TRUE) << GetEGLError(); | |
| config = {0}; | |
| EGLint num_config = 0; | |
| const EGLint attribute_list[] = {EGL_RED_SIZE, | |
| 8, | |
| EGL_GREEN_SIZE, | |
| 8, | |
| EGL_BLUE_SIZE, | |
| 8, | |
| EGL_ALPHA_SIZE, | |
| 8, | |
| EGL_SURFACE_TYPE, | |
| EGL_PBUFFER_BIT, | |
| EGL_CONFORMANT, | |
| EGL_OPENGL_ES2_BIT, | |
| EGL_RENDERABLE_TYPE, | |
| EGL_OPENGL_ES2_BIT, | |
| EGL_NONE}; | |
| result = ::eglChooseConfig(display, attribute_list, &config, 1, &num_config); | |
| FML_CHECK(result == EGL_TRUE) << GetEGLError(); | |
| FML_CHECK(num_config == 1) << GetEGLError(); | |
| { | |
| const EGLint context_attributes[] = { | |
| EGL_CONTEXT_CLIENT_VERSION, // | |
| 2, // | |
| EGL_NONE // | |
| }; | |
| onscreen_context = | |
| ::eglCreateContext(display, // display connection | |
| config, // config | |
| EGL_NO_CONTEXT, // sharegroup | |
| context_attributes // context attributes | |
| ); | |
| FML_CHECK(onscreen_context != EGL_NO_CONTEXT) << GetEGLError(); | |
| offscreen_context = | |
| ::eglCreateContext(display, // display connection | |
| config, // config | |
| onscreen_context, // sharegroup | |
| context_attributes // context attributes | |
| ); | |
| FML_CHECK(offscreen_context != EGL_NO_CONTEXT) << GetEGLError(); | |
| } | |
| } | |
| TestEGLContext::~TestEGLContext() { | |
| auto result = ::eglDestroyContext(display, onscreen_context); | |
| FML_CHECK(result == EGL_TRUE) << GetEGLError(); | |
| result = ::eglDestroyContext(display, offscreen_context); | |
| FML_CHECK(result == EGL_TRUE) << GetEGLError(); | |
| result = ::eglTerminate(display); | |
| FML_CHECK(result == EGL_TRUE); | |
| } | |
| } // namespace flutter::testing |