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 vector<string> GetExtensions::operator() (const RenderContext& context) const 165 { 166 const glw::Functions& gl = context.getFunctions(); 167 168 if (context.getType().getAPI() == ApiType::es(2,0)) 169 { 170 const char* result = (const char*)gl.getString(GL_EXTENSIONS); 171 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetString(GL_EXTENSIONS) failed"); 172 173 vector<string> extensions; 174 split(extensions, string(result)); 175 176 return extensions; 177 } 178 else 179 { 180 int numExtensions = 0; 181 vector<string> extensions; 182 183 gl.getIntegerv(GL_NUM_EXTENSIONS, &numExtensions); 184 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_NUM_EXTENSIONS) failed"); 185 186 extensions.resize(numExtensions); 187 for (int ndx = 0; ndx < numExtensions; ndx++) 188 extensions[ndx] = (const char*)gl.getStringi(GL_EXTENSIONS, ndx); 189 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetStringi(GL_EXTENSIONS, ndx) failed"); 190 191 return extensions; 192 } 193 } 194 195 set<int> GetCompressedTextureFormats::operator() (const RenderContext& context) const 196 { 197 const glw::Functions& gl = context.getFunctions(); 198 199 int numFormats = 0; 200 gl.getIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats); 201 202 vector<int> formats(numFormats); 203 if (numFormats > 0) 204 gl.getIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, &formats[0]); 205 206 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS) failed"); 207 208 set<int> formatSet; 209 std::copy(formats.begin(), formats.end(), std::inserter(formatSet, formatSet.begin())); 210 211 return formatSet; 212 } 213 214 // ContextInfo 215 216 ContextInfo::ContextInfo (const RenderContext& context) 217 : m_context(context) 218 { 219 } 220 221 ContextInfo::~ContextInfo (void) 222 { 223 } 224 225 int ContextInfo::getInt (int param) const 226 { 227 int val = -1; 228 m_context.getFunctions().getIntegerv(param, &val); 229 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetIntegerv() failed"); 230 return val; 231 } 232 233 bool ContextInfo::getBool (int param) const 234 { 235 glw::GLboolean val = GL_FALSE; 236 m_context.getFunctions().getBooleanv(param, &val); 237 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetBooleanv() failed"); 238 return val != GL_FALSE; 239 } 240 241 const char* ContextInfo::getString (int param) const 242 { 243 const char* str = (const char*)m_context.getFunctions().getString(param); 244 GLU_EXPECT_NO_ERROR(m_context.getFunctions().getError(), "glGetString() failed"); 245 return str; 246 } 247 248 bool ContextInfo::isCompressedTextureFormatSupported (int format) const 249 { 250 const set<int>& formats = m_compressedTextureFormats.getValue(m_context); 251 return formats.find(format) != formats.end(); 252 } 253 254 bool ContextInfo::isExtensionSupported (const char* name) const 255 { 256 const std::vector<std::string>& extensions = getExtensions(); 257 return std::find(extensions.begin(), extensions.end(), name) != extensions.end(); 258 } 259 260 ContextInfo* ContextInfo::create (const RenderContext& context) 261 { 262 // ES2 uses special variant that checks support for various shader features 263 // by trying to compile shader programs. 264 if (context.getType().getAPI() == ApiType::es(2,0)) 265 return new ES2ContextInfo(context); 266 267 return new ContextInfo(context); 268 } 269 270 } // glu 271