xref: /aosp_15_r20/external/deqp/framework/opengl/gluContextInfo.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
3  * ------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Context Info Class.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "gluContextInfo.hpp"
25 #include "gluRenderContext.hpp"
26 #include "gluShaderProgram.hpp"
27 #include "glwFunctions.hpp"
28 #include "glwEnums.hpp"
29 
30 #include <iterator>
31 #include <algorithm>
32 
33 using std::set;
34 using std::string;
35 using std::vector;
36 
37 namespace glu
38 {
39 
40 class TryCompileProgram
41 {
42 public:
43     // \note Assumes that shader pointer can be stored as is (eg. it is static data)
TryCompileProgram(const char * vertexSource,const char * fragmentSource)44     TryCompileProgram(const char *vertexSource, const char *fragmentSource)
45         : m_vertexSource(vertexSource)
46         , m_fragmentSource(fragmentSource)
47     {
48     }
49 
operator ()(const RenderContext & context) const50     bool operator()(const RenderContext &context) const
51     {
52         ShaderProgram program(context, ProgramSources()
53                                            << VertexSource(m_vertexSource) << FragmentSource(m_fragmentSource));
54         return program.isOk();
55     }
56 
57 private:
58     const char *m_vertexSource;
59     const char *m_fragmentSource;
60 };
61 
62 typedef CachedValue<bool, TryCompileProgram> IsProgramSupported;
63 
IsES3Compatible(const glw::Functions & gl)64 bool IsES3Compatible(const glw::Functions &gl)
65 {
66     // Detect compatible GLES context by querying GL_MAJOR_VERSION.
67     // This query does not exist on GLES2 so succeeding query implies GLES3+ context.
68     glw::GLint majorVersion = 0;
69     gl.getError();
70     gl.getIntegerv(GL_MAJOR_VERSION, &majorVersion);
71 
72     return (gl.getError() == GL_NO_ERROR);
73 }
74 
75 // ES2-specific context info
76 class ES2ContextInfo : public ContextInfo
77 {
78 public:
79     ES2ContextInfo(const RenderContext &context);
~ES2ContextInfo(void)80     ~ES2ContextInfo(void)
81     {
82     }
83 
isVertexUniformLoopSupported(void) const84     bool isVertexUniformLoopSupported(void) const
85     {
86         return m_vertexUniformLoopsSupported.getValue(m_context);
87     }
isVertexDynamicLoopSupported(void) const88     bool isVertexDynamicLoopSupported(void) const
89     {
90         return m_vertexDynamicLoopsSupported.getValue(m_context);
91     }
isFragmentHighPrecisionSupported(void) const92     bool isFragmentHighPrecisionSupported(void) const
93     {
94         return m_fragmentHighPrecisionSupported.getValue(m_context);
95     }
isFragmentUniformLoopSupported(void) const96     bool isFragmentUniformLoopSupported(void) const
97     {
98         return m_fragmentUniformLoopsSupported.getValue(m_context);
99     }
isFragmentDynamicLoopSupported(void) const100     bool isFragmentDynamicLoopSupported(void) const
101     {
102         return m_fragmentDynamicLoopsSupported.getValue(m_context);
103     }
104 
105 private:
106     IsProgramSupported m_vertexUniformLoopsSupported;
107     IsProgramSupported m_vertexDynamicLoopsSupported;
108 
109     IsProgramSupported m_fragmentHighPrecisionSupported;
110     IsProgramSupported m_fragmentUniformLoopsSupported;
111     IsProgramSupported m_fragmentDynamicLoopsSupported;
112 };
113 
114 static const char *s_defaultVertexShader   = "attribute highp vec4 a_position;\n"
115                                              "void main (void) {\n"
116                                              "    gl_Position = a_position;\n"
117                                              "}\n";
118 static const char *s_defaultFragmentShader = "void main (void) {\n"
119                                              "    gl_FragColor = vec4(1.0);\n"
120                                              "}\n";
121 
122 static const char *s_vertexUniformLoopsSupported = "attribute highp vec4    a_position;\n"
123                                                    "uniform int            u_numIters;\n"
124                                                    "void main (void) {\n"
125                                                    "    gl_Position = a_position;\n"
126                                                    "    for (int i = 0; i < u_numIters; i++)\n"
127                                                    "        gl_Position += vec4(0.1);\n"
128                                                    "}\n";
129 static const char *s_vertexDynamicLoopsSupported = "attribute highp vec4    a_position;\n"
130                                                    "uniform mediump float    a, b;\n"
131                                                    "void main (void) {\n"
132                                                    "    gl_Position = a_position;\n"
133                                                    "    int numIters = a < b ? int(3.0*b) : int(a_position.x);\n"
134                                                    "    for (int i = 0; i < numIters; i++)\n"
135                                                    "        gl_Position += vec4(0.1);\n"
136                                                    "}\n";
137 
138 static const char *s_fragmentHighPrecisionSupported = "varying highp vec4        v_color;\n"
139                                                       "void main (void) {\n"
140                                                       "    highp float tmp = v_color.r;\n"
141                                                       "    gl_FragColor = v_color;\n"
142                                                       "}\n";
143 static const char *s_fragmentUniformLoopsSupported  = "varying mediump vec4    v_color;\n"
144                                                       "uniform int            u_numIters;\n"
145                                                       "void main (void) {\n"
146                                                       "    gl_FragColor = v_color;\n"
147                                                       "    for (int i = 0; i < u_numIters; i++)\n"
148                                                       "        gl_FragColor += vec4(0.1);\n"
149                                                       "}\n";
150 static const char *s_fragmentDynamicLoopsSupported  = "varying mediump vec4    v_color;\n"
151                                                       "uniform mediump float    a, b;\n"
152                                                       "void main (void) {\n"
153                                                       "    gl_FragColor = v_color;\n"
154                                                       "    int numIters = a < b ? int(3.0*b) : int(v_color.x);\n"
155                                                       "    for (int i = 0; i < numIters; i++)\n"
156                                                       "        gl_FragColor += vec4(0.1);\n"
157                                                       "}\n";
158 
ES2ContextInfo(const RenderContext & context)159 ES2ContextInfo::ES2ContextInfo(const RenderContext &context)
160     : glu::ContextInfo(context)
161     , m_vertexUniformLoopsSupported(TryCompileProgram(s_vertexUniformLoopsSupported, s_defaultFragmentShader))
162     , m_vertexDynamicLoopsSupported(TryCompileProgram(s_vertexDynamicLoopsSupported, s_defaultFragmentShader))
163     , m_fragmentHighPrecisionSupported(TryCompileProgram(s_defaultVertexShader, s_fragmentHighPrecisionSupported))
164     , m_fragmentUniformLoopsSupported(TryCompileProgram(s_defaultVertexShader, s_fragmentUniformLoopsSupported))
165     , m_fragmentDynamicLoopsSupported(TryCompileProgram(s_defaultVertexShader, s_fragmentDynamicLoopsSupported))
166 {
167 }
168 
split(vector<string> & dst,const string & src)169 static void split(vector<string> &dst, const string &src)
170 {
171     size_t start = 0;
172     size_t end   = string::npos;
173 
174     while ((end = src.find(' ', start)) != string::npos)
175     {
176         dst.push_back(src.substr(start, end - start));
177         start = end + 1;
178     }
179 
180     if (start < end)
181         dst.push_back(src.substr(start, end - start));
182 }
183 
operator ()(const RenderContext & context) const184 set<int> GetCompressedTextureFormats::operator()(const RenderContext &context) const
185 {
186     const glw::Functions &gl = context.getFunctions();
187 
188     int numFormats = 0;
189     gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
190 
191     vector<int> formats(numFormats);
192     if (numFormats > 0)
193         gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]);
194 
195     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed");
196 
197     set<int> formatSet;
198     std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin()));
199 
200     return formatSet;
201 }
202 
203 // ContextInfo
204 
ContextInfo(const RenderContext & context)205 ContextInfo::ContextInfo(const RenderContext &context) : m_context(context)
206 {
207     const glw::Functions &gl = context.getFunctions();
208 
209     if (context.getType().getAPI() == ApiType::es(2, 0))
210     {
211         const char *result = (const char *)gl.getString(GL_EXTENSIONS);
212         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed");
213 
214         split(m_extensions, string(result));
215     }
216     else
217     {
218         int numExtensions = 0;
219 
220         gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
221         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed");
222 
223         m_extensions.resize(numExtensions);
224         for (int ndx = 0; ndx < numExtensions; ndx++)
225             m_extensions[ndx] = (const char *)gl.getStringi(GL_EXTENSIONS, ndx);
226         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed");
227     }
228 }
229 
~ContextInfo(void)230 ContextInfo::~ContextInfo(void)
231 {
232 }
233 
getInt(int param) const234 int ContextInfo::getInt(int param) const
235 {
236     int val = -1;
237     m_context.getFunctions().getIntegerv(param, &val);
238     GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed");
239     return val;
240 }
241 
getBool(int param) const242 bool ContextInfo::getBool(int param) const
243 {
244     glw::GLboolean val = GL_FALSE;
245     m_context.getFunctions().getBooleanv(param, &val);
246     GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed");
247     return val != GL_FALSE;
248 }
249 
getString(int param) const250 const char *ContextInfo::getString(int param) const
251 {
252     const char *str = (const char *)m_context.getFunctions().getString(param);
253     GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed");
254     return str;
255 }
256 
isCompressedTextureFormatSupported(int format) const257 bool ContextInfo::isCompressedTextureFormatSupported(int format) const
258 {
259     const set<int> &formats = m_compressedTextureFormats.getValue(m_context);
260     return formats.find(format) != formats.end();
261 }
262 
isExtensionSupported(const char * name) const263 bool ContextInfo::isExtensionSupported(const char *name) const
264 {
265     const std::vector<std::string> &extensions = getExtensions();
266     return std::find(extensions.begin(), extensions.end(), name) != extensions.end();
267 }
268 
isES3Compatible() const269 bool ContextInfo::isES3Compatible() const
270 {
271     return IsES3Compatible(m_context.getFunctions());
272 }
273 
create(const RenderContext & context)274 ContextInfo *ContextInfo::create(const RenderContext &context)
275 {
276     // ES2 uses special variant that checks support for various shader features
277     // by trying to compile shader programs.
278     if (context.getType().getAPI() == ApiType::es(2, 0))
279         return new ES2ContextInfo(context);
280 
281     return new ContextInfo(context);
282 }
283 
284 } // namespace glu
285