blob: e212549bebfc989ea87dce45acde66fb88cba3a3 [file] [log] [blame]
Lingfeng Yangee4aea32020-10-29 08:52:13 -07001/*
2* Copyright (C) 2016 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 "GLESVersionDetector.h"
18
Joshua Duong13890052022-08-26 13:30:50 -070019#include "OpenGLESDispatch/EGLDispatch.h"
Lingfeng Yangee4aea32020-10-29 08:52:13 -070020
Joshua Duongef2bbc22022-10-05 11:59:15 -070021#include "aemu/base/system/System.h"
22#include "aemu/base/misc/StringUtils.h"
Lingfeng Yangbfe3c722020-10-29 10:33:18 -070023#include "host-common/feature_control.h"
Joshua Duong9dfbd852022-11-14 13:12:59 -080024#include "host-common/opengl/misc.h"
Lingfeng Yangee4aea32020-10-29 08:52:13 -070025
26#include <algorithm>
27
Jason Macnaked0c9e62023-03-30 15:58:24 -070028namespace gfxstream {
29namespace gl {
30
Lingfeng Yangee4aea32020-10-29 08:52:13 -070031// Config + context attributes to query the underlying OpenGL if it is
32// a OpenGL ES backend. Only try for OpenGL ES 3, and assume OpenGL ES 2
33// exists (if it doesn't, this is the least of our problems).
34static const EGLint gles3ConfigAttribs[] =
35 { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
36 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT, EGL_NONE };
37
38static const EGLint pbufAttribs[] =
39 { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
40
41static const EGLint gles31Attribs[] =
42 { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
43 EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE };
44
45static const EGLint gles30Attribs[] =
46 { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
47 EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE };
48
49static bool sTryContextCreation(EGLDisplay dpy, GLESDispatchMaxVersion ver) {
50 EGLConfig config;
51 EGLSurface surface;
52
53 const EGLint* contextAttribs = nullptr;
54
55 // Assume ES2 capable.
56 if (ver == GLES_DISPATCH_MAX_VERSION_2) return true;
57
58 switch (ver) {
59 case GLES_DISPATCH_MAX_VERSION_3_0:
60 contextAttribs = gles30Attribs;
61 break;
62 case GLES_DISPATCH_MAX_VERSION_3_1:
63 contextAttribs = gles31Attribs;
64 break;
65 default:
66 break;
67 }
68
69 if (!contextAttribs) return false;
70
71 int numConfigs;
72 if (!s_egl.eglChooseConfig(
73 dpy, gles3ConfigAttribs, &config, 1, &numConfigs) ||
74 numConfigs == 0) {
75 return false;
76 }
77
78 surface = s_egl.eglCreatePbufferSurface(dpy, config, pbufAttribs);
79 if (surface == EGL_NO_SURFACE) {
80 return false;
81 }
82
83 EGLContext ctx = s_egl.eglCreateContext(dpy, config, EGL_NO_CONTEXT,
84 contextAttribs);
85
86 if (ctx == EGL_NO_CONTEXT) {
87 s_egl.eglDestroySurface(dpy, surface);
88 return false;
89 } else {
90 s_egl.eglDestroyContext(dpy, ctx);
91 s_egl.eglDestroySurface(dpy, surface);
92 return true;
93 }
94}
95
Jason Macnak26872122024-02-23 10:46:09 -080096GLESDispatchMaxVersion calcMaxVersionFromDispatch(const gfxstream::host::FeatureSet& features,
97 EGLDisplay dpy) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -070098 // TODO: 3.1 is the highest
99 GLESDispatchMaxVersion maxVersion =
100 GLES_DISPATCH_MAX_VERSION_3_1;
101
102 // TODO: CTS conformance for OpenGL ES 3.1
Jason Macnak26872122024-02-23 10:46:09 -0800103 bool playStoreImage = features.PlayStoreImage.enabled;
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700104
105 if (emugl::getRenderer() == SELECTED_RENDERER_HOST
106 || emugl::getRenderer() == SELECTED_RENDERER_SWIFTSHADER_INDIRECT
107 || emugl::getRenderer() == SELECTED_RENDERER_ANGLE_INDIRECT
108 || emugl::getRenderer() == SELECTED_RENDERER_ANGLE9_INDIRECT) {
109 if (s_egl.eglGetMaxGLESVersion) {
110 maxVersion =
111 (GLESDispatchMaxVersion)s_egl.eglGetMaxGLESVersion(dpy);
112 }
113 } else {
114 if (playStoreImage ||
115 !sTryContextCreation(dpy, GLES_DISPATCH_MAX_VERSION_3_1)) {
116 maxVersion = GLES_DISPATCH_MAX_VERSION_3_0;
117 if (!sTryContextCreation(dpy, GLES_DISPATCH_MAX_VERSION_3_0)) {
118 maxVersion = GLES_DISPATCH_MAX_VERSION_2;
119 }
120 }
121 }
122
123 if (playStoreImage) {
124 maxVersion =
125 std::min(maxVersion,
126 GLES_DISPATCH_MAX_VERSION_3_0);
127 }
128
129 int maj = 2; int min = 0;
130 switch (maxVersion) {
131 case GLES_DISPATCH_MAX_VERSION_2:
132 maj = 2; min = 0; break;
133 case GLES_DISPATCH_MAX_VERSION_3_0:
134 maj = 3; min = 0; break;
135 case GLES_DISPATCH_MAX_VERSION_3_1:
136 maj = 3; min = 1; break;
137 case GLES_DISPATCH_MAX_VERSION_3_2:
138 maj = 3; min = 2; break;
139 default:
140 break;
141 }
142
143 emugl::setGlesVersion(maj, min);
144
145 return maxVersion;
146}
147
148// For determining whether or not to use core profile OpenGL.
149// (Note: This does not affect the detection of possible core profile configs,
150// just whether to use them)
151bool shouldEnableCoreProfile() {
152 int dispatchMaj, dispatchMin;
153
154 emugl::getGlesVersion(&dispatchMaj, &dispatchMin);
155 return emugl::getRenderer() == SELECTED_RENDERER_HOST &&
156 dispatchMaj > 2;
157}
158
159void sAddExtensionIfSupported(GLESDispatchMaxVersion currVersion,
160 const std::string& from,
161 GLESDispatchMaxVersion extVersion,
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700162 const std::string& ext,
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700163 std::string& to) {
164 // If we chose a GLES version less than or equal to
165 // the |extVersion| the extension |ext| is tagged with,
166 // filter it according to the whitelist.
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700167 if (emugl::hasExtension(from.c_str(), ext.c_str()) &&
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700168 currVersion > extVersion) {
169 to += ext;
170 to += " ";
171 }
172}
173
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700174static bool sWhitelistedExtensionsGLES2(const std::string& hostExt) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700175
176#define WHITELIST(ext) \
177 if (hostExt == #ext) return true; \
178
179WHITELIST(GL_OES_compressed_ETC1_RGB8_texture)
180WHITELIST(GL_OES_depth24)
181WHITELIST(GL_OES_depth32)
182WHITELIST(GL_OES_depth_texture)
183WHITELIST(GL_OES_depth_texture_cube_map)
184WHITELIST(GL_OES_EGL_image)
185WHITELIST(GL_OES_EGL_image_external)
186WHITELIST(GL_OES_EGL_sync)
187WHITELIST(GL_OES_element_index_uint)
188WHITELIST(GL_OES_framebuffer_object)
189WHITELIST(GL_OES_packed_depth_stencil)
190WHITELIST(GL_OES_rgb8_rgba8)
191WHITELIST(GL_OES_standard_derivatives)
192WHITELIST(GL_OES_texture_float)
193WHITELIST(GL_OES_texture_float_linear)
194WHITELIST(GL_OES_texture_half_float)
195WHITELIST(GL_OES_texture_half_float_linear)
196WHITELIST(GL_OES_texture_npot)
197WHITELIST(GL_OES_texture_3D)
Yahan Zhoufa337122023-10-31 15:44:03 -0700198WHITELIST(GL_OVR_multiview2)
199WHITELIST(GL_EXT_multiview_texture_multisample)
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700200WHITELIST(GL_EXT_blend_minmax)
201WHITELIST(GL_EXT_color_buffer_half_float)
202WHITELIST(GL_EXT_draw_buffers)
203WHITELIST(GL_EXT_instanced_arrays)
204WHITELIST(GL_EXT_occlusion_query_boolean)
205WHITELIST(GL_EXT_read_format_bgra)
Gurchetan Singh5ac22872022-08-25 13:49:56 -0700206WHITELIST(GL_EXT_texture_compression_rgtc)
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700207WHITELIST(GL_EXT_texture_filter_anisotropic)
208WHITELIST(GL_EXT_texture_format_BGRA8888)
209WHITELIST(GL_EXT_texture_rg)
210WHITELIST(GL_ANGLE_framebuffer_blit)
211WHITELIST(GL_ANGLE_framebuffer_multisample)
212WHITELIST(GL_ANGLE_instanced_arrays)
213WHITELIST(GL_CHROMIUM_texture_filtering_hint)
214WHITELIST(GL_NV_fence)
215WHITELIST(GL_NV_framebuffer_blit)
216WHITELIST(GL_NV_read_depth)
217
Gurchetan Singhf7fae322022-08-25 14:20:35 -0700218#if defined(__linux__)
219WHITELIST(GL_EXT_texture_compression_bptc)
220WHITELIST(GL_EXT_texture_compression_s3tc)
221#endif
222
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700223#undef WHITELIST
224
225 return false;
226}
227
Jason Macnak26872122024-02-23 10:46:09 -0800228std::string filterExtensionsBasedOnMaxVersion(const gfxstream::host::FeatureSet& features,
229 GLESDispatchMaxVersion ver,
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700230 const std::string& exts) {
231 // We need to advertise ES 2 extensions if:
232 // a. the dispatch version on the host is ES 2
233 // b. the guest image is not updated for ES 3+
234 // (GLESDynamicVersion is disabled)
Jason Macnak26872122024-02-23 10:46:09 -0800235 if (ver > GLES_DISPATCH_MAX_VERSION_2 && features.GlesDynamicVersion.enabled) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700236 return exts;
237 }
238
239 std::string filteredExtensions;
240 filteredExtensions.reserve(4096);
Lingfeng Yang1e4f28a2020-11-09 14:56:56 -0800241 auto add = [&filteredExtensions](const std::string& hostExt) {
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700242 if (!hostExt.empty() &&
243 sWhitelistedExtensionsGLES2(hostExt)) {
244 filteredExtensions += hostExt;
245 filteredExtensions += " ";
246 }
247 };
248
Lingfeng Yangbfe3c722020-10-29 10:33:18 -0700249 android::base::split<std::string>(exts, " ", add);
Lingfeng Yangee4aea32020-10-29 08:52:13 -0700250
251 return filteredExtensions;
252}
Jason Macnaked0c9e62023-03-30 15:58:24 -0700253
254} // namespace gl
255} // namespace gfxstream