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::vector; 34 using std::string; 35 using std::set; 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) 44 TryCompileProgram (const char* vertexSource, const char* fragmentSource) 45 : m_vertexSource (vertexSource) 46 , m_fragmentSource (fragmentSource) 47 { 48 } 49 50 bool operator() (const RenderContext& context) const 51 { 52 ShaderProgram program(context, 53 ProgramSources() << VertexSource(m_vertexSource) 54 << FragmentSource(m_fragmentSource)); 55 return program.isOk(); 56 } 57 58 private: 59 const char* m_vertexSource; 60 const char* m_fragmentSource; 61 }; 62 63 typedef CachedValue<bool, TryCompileProgram> IsProgramSupported; 64 65 // ES2-specific context info 66 class ES2ContextInfo : public ContextInfo 67 { 68 public: 69 ES2ContextInfo (const RenderContext& context); 70 ~ES2ContextInfo (void) {} 71 72 bool isVertexUniformLoopSupported (void) const { return m_vertexUniformLoopsSupported.getValue(m_context); } 73 bool isVertexDynamicLoopSupported (void) const { return m_vertexDynamicLoopsSupported.getValue(m_context); } 74 bool isFragmentHighPrecisionSupported (void) const { return m_fragmentHighPrecisionSupported.getValue(m_context); } 75 bool isFragmentUniformLoopSupported (void) const { return m_fragmentUniformLoopsSupported.getValue(m_context); } 76 bool isFragmentDynamicLoopSupported (void) const { return m_fragmentDynamicLoopsSupported.getValue(m_context); } 77 78 private: 79 IsProgramSupported m_vertexUniformLoopsSupported; 80 IsProgramSupported m_vertexDynamicLoopsSupported; 81 82 IsProgramSupported m_fragmentHighPrecisionSupported; 83 IsProgramSupported m_fragmentUniformLoopsSupported; 84 IsProgramSupported m_fragmentDynamicLoopsSupported; 85 }; 86 87 static const char* s_defaultVertexShader = 88 "attribute highp vec4 a_position;\n" 89 "void main (void) {\n" 90 " gl_Position = a_position;\n" 91 "}\n"; 92 static const char* s_defaultFragmentShader = 93 "void main (void) {\n" 94 " gl_FragColor = vec4(1.0);\n" 95 "}\n"; 96 97 static const char* s_vertexUniformLoopsSupported = 98 "attribute highp vec4 a_position;\n" 99 "uniform int u_numIters;\n" 100 "void main (void) {\n" 101 " gl_Position = a_position;\n" 102 " for (int i = 0; i < u_numIters; i++)\n" 103 " gl_Position += vec4(0.1);\n" 104 "}\n"; 105 static const char* s_vertexDynamicLoopsSupported = 106 "attribute highp vec4 a_position;\n" 107 "uniform mediump float a, b;\n" 108 "void main (void) {\n" 109 " gl_Position = a_position;\n" 110 " int numIters = a < b ? int(3.0*b) : int(a_position.x);\n" 111 " for (int i = 0; i < numIters; i++)\n" 112 " gl_Position += vec4(0.1);\n" 113 "}\n"; 114 115 static const char* s_fragmentHighPrecisionSupported = 116 "varying highp vec4 v_color;\n" 117 "void main (void) {\n" 118 " highp float tmp = v_color.r;\n" 119 " gl_FragColor = v_color;\n" 120 "}\n"; 121 static const char* s_fragmentUniformLoopsSupported = 122 "varying mediump vec4 v_color;\n" 123 "uniform int u_numIters;\n" 124 "void main (void) {\n" 125 " gl_FragColor = v_color;\n" 126 " for (int i = 0; i < u_numIters; i++)\n" 127 " gl_FragColor += vec4(0.1);\n" 128 "}\n"; 129 static const char* s_fragmentDynamicLoopsSupported = 130 "varying mediump vec4 v_color;\n" 131 "uniform mediump float a, b;\n" 132 "void main (void) {\n" 133 " gl_FragColor = v_color;\n" 134 " int numIters = a < b ? int(3.0*b) : int(v_color.x);\n" 135 " for (int i = 0; i < numIters; i++)\n" 136 " gl_FragColor += vec4(0.1);\n" 137 "}\n"; 138 139 ES2ContextInfo::ES2ContextInfo (const RenderContext& context) 140 : glu::ContextInfo (context) 141 , m_vertexUniformLoopsSupported (TryCompileProgram(s_vertexUniformLoopsSupported, s_defaultFragmentShader)) 142 , m_vertexDynamicLoopsSupported (TryCompileProgram(s_vertexDynamicLoopsSupported, s_defaultFragmentShader)) 143 , m_fragmentHighPrecisionSupported (TryCompileProgram(s_defaultVertexShader, s_fragmentHighPrecisionSupported)) 144 , m_fragmentUniformLoopsSupported (TryCompileProgram(s_defaultVertexShader, s_fragmentUniformLoopsSupported)) 145 , m_fragmentDynamicLoopsSupported (TryCompileProgram(s_defaultVertexShader, s_fragmentDynamicLoopsSupported)) 146 { 147 } 148 149 static void split (vector<string>& dst, const string& src) 150 { 151 size_t start = 0; 152 size_t end = string::npos; 153 154 while ((end = src.find(' ', start)) != string::npos) 155 { 156 dst.push_back(src.substr(start, end-start)); 157 start = end+1; 158 } 159 160 if (start < end) 161 dst.push_back(src.substr(start, end-start)); 162 } 163 164 set<int> GetCompressedTextureFormats::operator() (const RenderContext& context) const 165 { 166 const glw::Functions& gl = context.getFunctions(); 167 168 int numFormats = 0; 169 gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); 170 171 vector<int> formats(numFormats); 172 if (numFormats > 0) 173 gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]); 174 175 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed"); 176 177 set<int> formatSet; 178 std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin())); 179 180 return formatSet; 181 } 182 183 // ContextInfo 184 185 ContextInfo::ContextInfo (const RenderContext& context) 186 : m_context(context) 187 { 188 const glw::Functions& gl = context.getFunctions(); 189 190 if (context.getType().getAPI() == ApiType::es(2,0)) 191 { 192 const char* result = (const char*)gl.getString(GL_EXTENSIONS); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed"); 194 195 split(m_extensions, string(result)); 196 } 197 else 198 { 199 int numExtensions = 0; 200 201 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions); 202 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed"); 203 204 m_extensions.resize(numExtensions); 205 for (int ndx = 0; ndx < numExtensions; ndx++) 206 m_extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, ndx); 207 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed"); 208 } 209 } 210 211 ContextInfo::~ContextInfo (void) 212 { 213 } 214 215 int ContextInfo::getInt (int param) const 216 { 217 int val = -1; 218 m_context.getFunctions().getIntegerv(param, &val); 219 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed"); 220 return val; 221 } 222 223 bool ContextInfo::getBool (int param) const 224 { 225 glw::GLboolean val = GL_FALSE; 226 m_context.getFunctions().getBooleanv(param, &val); 227 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed"); 228 return val != GL_FALSE; 229 } 230 231 const char* ContextInfo::getString (int param) const 232 { 233 const char* str = (const char*)m_context.getFunctions().getString(param); 234 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed"); 235 return str; 236 } 237 238 bool ContextInfo::isCompressedTextureFormatSupported (int format) const 239 { 240 const set<int>& formats = m_compressedTextureFormats.getValue(m_context); 241 return formats.find(format) != formats.end(); 242 } 243 244 bool ContextInfo::isExtensionSupported (const char* name) const 245 { 246 const std::vector<std::string>& extensions = getExtensions(); 247 return std::find(extensions.begin(), extensions.end(), name) != extensions.end(); 248 } 249 250 ContextInfo* ContextInfo::create (const RenderContext& context) 251 { 252 // ES2 uses special variant that checks support for various shader features 253 // by trying to compile shader programs. 254 if (context.getType().getAPI() == ApiType::es(2,0)) 255 return new ES2ContextInfo(context); 256 257 return new ContextInfo(context); 258 } 259 260 } // glu 261