• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
19 #include "EGLDispatch.h"
20 
21 #include "base/System.h"
22 #include "base/StringUtils.h"
23 #include "host-common/feature_control.h"
24 #include "host-common/misc.h"
25 
26 #include <algorithm>
27 
28 // Config + context attributes to query the underlying OpenGL if it is
29 // a OpenGL ES backend. Only try for OpenGL ES 3, and assume OpenGL ES 2
30 // exists (if it doesn't, this is the least of our problems).
31 static const EGLint gles3ConfigAttribs[] =
32     { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
33       EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT, EGL_NONE };
34 
35 static const EGLint pbufAttribs[] =
36     { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
37 
38 static const EGLint gles31Attribs[] =
39    { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
40      EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE };
41 
42 static const EGLint gles30Attribs[] =
43    { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
44      EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE };
45 
sTryContextCreation(EGLDisplay dpy,GLESDispatchMaxVersion ver)46 static bool sTryContextCreation(EGLDisplay dpy, GLESDispatchMaxVersion ver) {
47     EGLConfig config;
48     EGLSurface surface;
49 
50     const EGLint* contextAttribs = nullptr;
51 
52     // Assume ES2 capable.
53     if (ver == GLES_DISPATCH_MAX_VERSION_2) return true;
54 
55     switch (ver) {
56     case GLES_DISPATCH_MAX_VERSION_3_0:
57         contextAttribs = gles30Attribs;
58         break;
59     case GLES_DISPATCH_MAX_VERSION_3_1:
60         contextAttribs = gles31Attribs;
61         break;
62     default:
63         break;
64     }
65 
66     if (!contextAttribs) return false;
67 
68     int numConfigs;
69     if (!s_egl.eglChooseConfig(
70             dpy, gles3ConfigAttribs, &config, 1, &numConfigs) ||
71         numConfigs == 0) {
72         return false;
73     }
74 
75     surface = s_egl.eglCreatePbufferSurface(dpy, config, pbufAttribs);
76     if (surface == EGL_NO_SURFACE) {
77         return false;
78     }
79 
80     EGLContext ctx = s_egl.eglCreateContext(dpy, config, EGL_NO_CONTEXT,
81                                             contextAttribs);
82 
83     if (ctx == EGL_NO_CONTEXT) {
84         s_egl.eglDestroySurface(dpy, surface);
85         return false;
86     } else {
87         s_egl.eglDestroyContext(dpy, ctx);
88         s_egl.eglDestroySurface(dpy, surface);
89         return true;
90     }
91 }
92 
calcMaxVersionFromDispatch(EGLDisplay dpy)93 GLESDispatchMaxVersion calcMaxVersionFromDispatch(EGLDisplay dpy) {
94 
95     // TODO: 3.1 is the highest
96     GLESDispatchMaxVersion maxVersion =
97        GLES_DISPATCH_MAX_VERSION_3_1;
98 
99     // TODO: CTS conformance for OpenGL ES 3.1
100     bool playStoreImage = feature_is_enabled(
101             kFeature_PlayStoreImage);
102 
103     if (emugl::getRenderer() == SELECTED_RENDERER_HOST
104         || emugl::getRenderer() == SELECTED_RENDERER_SWIFTSHADER_INDIRECT
105         || emugl::getRenderer() == SELECTED_RENDERER_ANGLE_INDIRECT
106         || emugl::getRenderer() == SELECTED_RENDERER_ANGLE9_INDIRECT) {
107         if (s_egl.eglGetMaxGLESVersion) {
108             maxVersion =
109                 (GLESDispatchMaxVersion)s_egl.eglGetMaxGLESVersion(dpy);
110         }
111     } else {
112         if (playStoreImage ||
113             !sTryContextCreation(dpy, GLES_DISPATCH_MAX_VERSION_3_1)) {
114             maxVersion = GLES_DISPATCH_MAX_VERSION_3_0;
115             if (!sTryContextCreation(dpy, GLES_DISPATCH_MAX_VERSION_3_0)) {
116                 maxVersion = GLES_DISPATCH_MAX_VERSION_2;
117             }
118         }
119     }
120 
121     if (playStoreImage) {
122         maxVersion =
123             std::min(maxVersion,
124                      GLES_DISPATCH_MAX_VERSION_3_0);
125     }
126 
127     int maj = 2; int min = 0;
128     switch (maxVersion) {
129         case GLES_DISPATCH_MAX_VERSION_2:
130             maj = 2; min = 0; break;
131         case GLES_DISPATCH_MAX_VERSION_3_0:
132             maj = 3; min = 0; break;
133         case GLES_DISPATCH_MAX_VERSION_3_1:
134             maj = 3; min = 1; break;
135         case GLES_DISPATCH_MAX_VERSION_3_2:
136             maj = 3; min = 2; break;
137         default:
138             break;
139     }
140 
141     emugl::setGlesVersion(maj, min);
142 
143     return maxVersion;
144 }
145 
146 // For determining whether or not to use core profile OpenGL.
147 // (Note: This does not affect the detection of possible core profile configs,
148 // just whether to use them)
shouldEnableCoreProfile()149 bool shouldEnableCoreProfile() {
150     int dispatchMaj, dispatchMin;
151 
152     emugl::getGlesVersion(&dispatchMaj, &dispatchMin);
153     return emugl::getRenderer() == SELECTED_RENDERER_HOST &&
154            dispatchMaj > 2;
155 }
156 
sAddExtensionIfSupported(GLESDispatchMaxVersion currVersion,const std::string & from,GLESDispatchMaxVersion extVersion,const std::string & ext,std::string & to)157 void sAddExtensionIfSupported(GLESDispatchMaxVersion currVersion,
158                               const std::string& from,
159                               GLESDispatchMaxVersion extVersion,
160                               const std::string& ext,
161                               std::string& to) {
162     // If we chose a GLES version less than or equal to
163     // the |extVersion| the extension |ext| is tagged with,
164     // filter it according to the whitelist.
165     if (emugl::hasExtension(from.c_str(), ext.c_str()) &&
166         currVersion > extVersion) {
167         to += ext;
168         to += " ";
169     }
170 }
171 
sWhitelistedExtensionsGLES2(const std::string & hostExt)172 static bool sWhitelistedExtensionsGLES2(const std::string& hostExt) {
173 
174 #define WHITELIST(ext) \
175     if (hostExt == #ext) return true; \
176 
177 WHITELIST(GL_OES_compressed_ETC1_RGB8_texture)
178 WHITELIST(GL_OES_depth24)
179 WHITELIST(GL_OES_depth32)
180 WHITELIST(GL_OES_depth_texture)
181 WHITELIST(GL_OES_depth_texture_cube_map)
182 WHITELIST(GL_OES_EGL_image)
183 WHITELIST(GL_OES_EGL_image_external)
184 WHITELIST(GL_OES_EGL_sync)
185 WHITELIST(GL_OES_element_index_uint)
186 WHITELIST(GL_OES_framebuffer_object)
187 WHITELIST(GL_OES_packed_depth_stencil)
188 WHITELIST(GL_OES_rgb8_rgba8)
189 WHITELIST(GL_OES_standard_derivatives)
190 WHITELIST(GL_OES_texture_float)
191 WHITELIST(GL_OES_texture_float_linear)
192 WHITELIST(GL_OES_texture_half_float)
193 WHITELIST(GL_OES_texture_half_float_linear)
194 WHITELIST(GL_OES_texture_npot)
195 WHITELIST(GL_OES_texture_3D)
196 WHITELIST(GL_EXT_blend_minmax)
197 WHITELIST(GL_EXT_color_buffer_half_float)
198 WHITELIST(GL_EXT_draw_buffers)
199 WHITELIST(GL_EXT_instanced_arrays)
200 WHITELIST(GL_EXT_occlusion_query_boolean)
201 WHITELIST(GL_EXT_read_format_bgra)
202 WHITELIST(GL_EXT_texture_filter_anisotropic)
203 WHITELIST(GL_EXT_texture_format_BGRA8888)
204 WHITELIST(GL_EXT_texture_rg)
205 WHITELIST(GL_ANGLE_framebuffer_blit)
206 WHITELIST(GL_ANGLE_framebuffer_multisample)
207 WHITELIST(GL_ANGLE_instanced_arrays)
208 WHITELIST(GL_CHROMIUM_texture_filtering_hint)
209 WHITELIST(GL_NV_fence)
210 WHITELIST(GL_NV_framebuffer_blit)
211 WHITELIST(GL_NV_read_depth)
212 
213 #undef WHITELIST
214 
215     return false;
216 }
217 
filterExtensionsBasedOnMaxVersion(GLESDispatchMaxVersion ver,const std::string & exts)218 std::string filterExtensionsBasedOnMaxVersion(GLESDispatchMaxVersion ver,
219                                               const std::string& exts) {
220     // We need to advertise ES 2 extensions if:
221     // a. the dispatch version on the host is ES 2
222     // b. the guest image is not updated for ES 3+
223     // (GLESDynamicVersion is disabled)
224     if (ver > GLES_DISPATCH_MAX_VERSION_2 &&
225         feature_is_enabled(
226             kFeature_GLESDynamicVersion)) {
227         return exts;
228     }
229 
230     std::string filteredExtensions;
231     filteredExtensions.reserve(4096);
232     auto add = [&filteredExtensions](const std::string& hostExt) {
233         if (!hostExt.empty() &&
234             sWhitelistedExtensionsGLES2(hostExt)) {
235             filteredExtensions += hostExt;
236             filteredExtensions += " ";
237         }
238     };
239 
240     android::base::split<std::string>(exts, " ", add);
241 
242     return filteredExtensions;
243 }
244