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