blob: 20f9c66eca6773e2942b19e10cd4c722f9a765b7 [file] [log] [blame]
Jason Macnakf9d926f2023-09-01 14:55:56 -07001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Egl.h"
18
19#include <GLES/gl.h>
20
21namespace gfxstream {
22namespace {
23
24constexpr const char kEglLib[] = "libEGL.so";
25constexpr const char kEglLibAlt[] = "libEGL.so.1";
26
27gfxstream::expected<Lib, std::string> LoadEglLib() {
28 for (const auto* possible_name : {kEglLib, kEglLibAlt}) {
29 auto result = Lib::Load(possible_name);
30 if (result.ok()) {
31 return std::move(result.value());
32 }
33 }
34 return gfxstream::unexpected("Failed to load libEGL.");
35}
36
37} // namespace
38
39/*static*/
40gfxstream::expected<Egl, std::string> Egl::Load() {
41 Egl egl;
42 egl.mLib = GFXSTREAM_EXPECT(LoadEglLib());
43
44#define LOAD_EGL_FUNCTION_POINTER(return_type, function_name, signature) \
45 egl.function_name = reinterpret_cast<return_type(GL_APIENTRY*) signature>( \
46 egl.mLib.GetSymbol(#function_name)); \
47 if (egl.function_name == nullptr) { \
48 egl.function_name = reinterpret_cast<return_type(GL_APIENTRY*) signature>( \
49 egl.eglGetProcAddress(#function_name)); \
50 }
51
52 FOR_EACH_EGL_FUNCTION(LOAD_EGL_FUNCTION_POINTER);
53
54 GFXSTREAM_EXPECT(egl.Init());
55
56 return std::move(egl);
57}
58
59gfxstream::expected<Ok, std::string> Egl::Init() {
60 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
61 if (display == EGL_NO_DISPLAY) {
62 return gfxstream::unexpected("Failed to get default display");
63 }
64
65 EGLint clientVersionMajor = 0;
66 EGLint clientVersionMinor = 0;
67 if (eglInitialize(display, &clientVersionMajor, &clientVersionMinor) != EGL_TRUE) {
68 return gfxstream::unexpected("Failed to initialize display.");
69 }
70
71 const std::string vendorString = eglQueryString(display, EGL_VENDOR);
72 if (vendorString.empty()) {
73 return gfxstream::unexpected("Failed to query vendor.");
74 }
75
76 const std::string extensionsString = eglQueryString(display, EGL_EXTENSIONS);
77 if (extensionsString.empty()) {
78 return gfxstream::unexpected("Failed to query extensions.");
79 }
80
81 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
82 return gfxstream::unexpected("Failed to bind GLES API.");
83 }
84
85 const EGLint attribs[] = {
86 // clang-format off
87 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
88 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
89 EGL_RED_SIZE, 8,
90 EGL_GREEN_SIZE, 8,
91 EGL_BLUE_SIZE, 8,
92 EGL_ALPHA_SIZE, 8,
93 EGL_NONE,
94 // clang-format on
95 };
96
97 EGLConfig config;
98 EGLint numConfigs = 0;
99 if (eglChooseConfig(display, attribs, &config, 1, &numConfigs) != EGL_TRUE) {
100 return gfxstream::unexpected("Failed to find matching framebuffer config.");
101 }
102
103 const EGLint pbufferAttribs[] = {
104 // clang-format off
105 EGL_WIDTH, 720,
106 EGL_HEIGHT, 720,
107 EGL_NONE,
108 // clang-format on
109 };
110
111 EGLSurface primarySurface = eglCreatePbufferSurface(display, config, pbufferAttribs);
112 if (primarySurface == EGL_NO_SURFACE) {
113 return gfxstream::unexpected("Failed to create EGL surface.");
114 }
115
116 const EGLint contextAttribs[] = {
117 // clang-format off
118 EGL_CONTEXT_CLIENT_VERSION, 3,
119 EGL_NONE
120 // clang-format on
121 };
122
123 EGLContext primaryContext = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
124 if (primaryContext == EGL_NO_CONTEXT) {
125 return gfxstream::unexpected("Failed to create EGL context.");
126 }
127
128 if (eglMakeCurrent(display, primarySurface, primarySurface, primaryContext) == EGL_FALSE) {
129 return gfxstream::unexpected("Failed to make primary EGL context/surface current.");
130 }
131
132 return {};
133}
134
135} // namespace gfxstream