45 class CapabilityValue {
48 GraphicsManager::ShaderPrecision,
49 std::vector<GLint> > CapabilityVariant;
50 typedef void(*Getter)(GraphicsManager* gm, CapabilityValue* cv);
52 CapabilityValue() : uninitialized_(true) {}
53 CapabilityValue(GLenum enum1_in, GLenum enum2_in,
const Getter& getter_in)
57 uninitialized_(false) {}
59 CapabilityValue& operator=(
const CapabilityValue& other) {
64 DCHECK(uninitialized_ && !other.uninitialized_);
65 enum1_ = other.enum1_;
66 enum2_ = other.enum2_;
67 getter_ = other.getter_;
68 uninitialized_ =
false;
74 const CapabilityVariant& GetValue(GraphicsManager* gm) {
76 populated_flag_.CallOnce(std::bind(getter_, gm,
this));
81 static void GetIntVector(GraphicsManager* gm, CapabilityValue* cv) {
83 gm->GetIntegerv(cv->enum2_, &count);
84 std::vector<GLint> values(count);
86 gm->GetIntegerv(cv->enum1_, &values[0]);
87 cv->value_.Set(values);
90 static void GetFloat(GraphicsManager* gm, CapabilityValue* cv) {
92 gm->GetFloatv(cv->enum1_, &val);
96 static void GetFloatRange(GraphicsManager* gm, CapabilityValue* cv) {
99 gm->GetFloatv(cv->enum1_, val);
103 static void GetInt(GraphicsManager* gm, CapabilityValue* cv) {
105 gm->GetIntegerv(cv->enum1_, &val);
109 static void GetIntRange(GraphicsManager* gm, CapabilityValue* cv) {
112 gm->GetIntegerv(cv->enum1_, val);
116 static void GetShaderPrecision(GraphicsManager* gm, CapabilityValue* cv) {
118 range[0] = range[1] = 0;
119 gm->GetShaderPrecisionFormat(cv->enum1_, cv->enum2_, range,
121 cv->value_.Set(GraphicsManager::ShaderPrecision(
128 CapabilityVariant value_;
130 base::OnceFlag populated_flag_;
134 class GraphicsManager::CapabilityHelper {
137 #define ION_SINGLE_CAP(index, enum, getter) \
138 capabilities_[index] = CapabilityValue(enum, GL_NONE, CapabilityValue::getter)
139 #define ION_DOUBLE_CAP(index, enum1, enum2, getter) \
140 capabilities_[index] = CapabilityValue(enum1, enum2, CapabilityValue::getter)
147 GL_NUM_COMPRESSED_TEXTURE_FORMATS, GetIntVector);
149 GL_IMPLEMENTATION_COLOR_READ_FORMAT, GetInt);
151 GL_IMPLEMENTATION_COLOR_READ_TYPE, GetInt);
153 GL_MAX_COLOR_ATTACHMENTS, GetInt);
155 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GetInt);
160 GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, GetInt);
170 GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, GetInt);
172 GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, GetInt);
174 GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, GetInt);
176 GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, GetInt);
180 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GetInt);
182 GL_MAX_VERTEX_UNIFORM_COMPONENTS, GetInt);
187 GL_NUM_SHADER_BINARY_FORMATS, GetIntVector);
189 GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, GetInt);
194 GL_HIGH_FLOAT, GetShaderPrecision);
196 GL_HIGH_INT, GetShaderPrecision);
198 GL_LOW_FLOAT, GetShaderPrecision);
200 GL_LOW_INT, GetShaderPrecision);
202 GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, GetShaderPrecision);
204 GL_MEDIUM_INT, GetShaderPrecision);
206 GL_HIGH_FLOAT, GetShaderPrecision);
208 GL_HIGH_INT, GetShaderPrecision);
210 GL_LOW_FLOAT, GetShaderPrecision);
212 GL_LOW_INT, GetShaderPrecision);
214 GL_MEDIUM_FLOAT, GetShaderPrecision);
216 GL_MEDIUM_INT, GetShaderPrecision);
218 #undef ION_SINGLE_CAP
219 #undef ION_DOUBLE_CAP
222 ~CapabilityHelper() {}
225 return capabilities_[cap].GetValue(gm);
242 class GraphicsManager::FunctionGroup {
247 available_functions_(),
248 missing_functions_() {}
250 void AddFunction(
const std::string&
name,
void*
function) {
251 #if defined(ION_COVERAGE)
252 available_functions_.push_back(name);
253 #else // COV_NF_START
254 if (
function == NULL)
255 missing_functions_.push_back(name);
257 available_functions_.push_back(name);
259 complete_ = complete_ && (
function != NULL);
261 bool IsComplete()
const {
return complete_ && enabled_; }
262 bool IsEnabled()
const {
return enabled_; }
263 void SetEnabled(
bool enable) { enabled_ = enable; }
264 #if !defined(ION_COVERAGE) // COV_NF_START
265 const std::vector<std::string>& GetMissingFunctions()
const {
266 return missing_functions_;
273 std::vector<std::string> available_functions_;
274 std::vector<std::string> missing_functions_;
285 class GraphicsManager::WrapperVecHolder :
public base::Allocatable {
288 WrapperVec& GetWrappers() {
return wrappers_; }
291 WrapperVec wrappers_;
294 GraphicsManager::WrapperVecHolder* GraphicsManager::GetWrapperVecHolder() {
296 base::ThreadLocalObject<WrapperVecHolder>, s_helper);
297 return s_helper->Get();
309 : wrappers_(GetAllocator()),
310 function_groups_(GetAllocator()),
311 capability_helper_(new CapabilityHelper),
312 wrapped_function_names_(*this),
313 is_error_checking_enabled_(false),
314 tracing_ostream_(NULL),
316 gl_api_standard_(kEs),
317 gl_profile_type_(kCompatibilityProfile) {
322 : wrappers_(GetAllocator()),
323 function_groups_(GetAllocator()),
324 capability_helper_(new CapabilityHelper),
325 wrapped_function_names_(*this),
326 is_error_checking_enabled_(false),
327 tracing_ostream_(NULL),
329 gl_api_standard_(kEs),
330 gl_profile_type_(kCompatibilityProfile) {
337 void GraphicsManager::Init(
bool init_functions_from_gl) {
338 WrapperVecHolder* wrapper_holder = GetWrapperVecHolder();
341 DCHECK(wrapper_holder != NULL);
342 WrapperVec& thread_wrappers = wrapper_holder->GetWrappers();
343 DCHECK(!thread_wrappers.empty());
346 wrappers_ = thread_wrappers;
347 thread_wrappers.clear();
348 thread_wrappers.reserve(0U);
350 if (init_functions_from_gl) {
353 #if !defined(ION_COVERAGE) // COV_NF_START
354 if (!function_groups_[
kCore].IsComplete()) {
355 LOG(
ERROR) <<
"***ION: Some required OpenGL functions could not be "
356 <<
"found. Either there is no valid OpenGL context, or the "
357 <<
"following functions are missing from your OpenGL "
359 const std::vector<std::string>& missing =
360 function_groups_[
kCore].GetMissingFunctions();
361 for (
size_t i = 0; i < missing.size(); i++) {
362 LOG(
ERROR) <<
" " << missing[i].c_str();
369 template <
typename T>
372 capability_helper_->GetCapabilityValue(
this, cap);
373 const T& val = value.
Get<
T>();
375 LOG(
WARNING) <<
"Invalid type requested for capability " << cap;
379 template const int GraphicsManager::GetCapabilityValue<int>(
381 template const float GraphicsManager::GetCapabilityValue<float>(
384 GraphicsManager::GetCapabilityValue<math::Range1f>(Capability cap);
386 GraphicsManager::GetCapabilityValue<math::Range1i>(Capability cap);
388 GraphicsManager::GetCapabilityValue<GraphicsManager::ShaderPrecision>(
390 template const std::vector<int>
391 GraphicsManager::GetCapabilityValue<std::vector<int> >(Capability cap);
394 return function_groups_.size() > 0 && function_groups_[group].IsComplete();
401 void GraphicsManager::AddWrapper(WrapperBase* wrapper) {
402 WrapperVecHolder* holder = GetWrapperVecHolder();
403 WrapperVec& thread_wrappers = holder->GetWrappers();
404 if (thread_wrappers.capacity() < 64U) {
405 thread_wrappers.reserve(64U);
407 thread_wrappers.push_back(wrapper);
410 void GraphicsManager::AddFunctionToGroup(FunctionGroupId group,
411 const char* func_name,
413 if (function_groups_.size() == 0) {
416 function_groups_[group].AddFunction(func_name,
function);
421 if (function_groups_.size() > 0)
422 function_groups_[group].SetEnabled(enable);
438 void GraphicsManager::InitFunctions() {
439 const size_t num_wrappers = wrappers_.size();
440 for (
size_t i = 0; i < num_wrappers; ++i) {
441 if (wrappers_[i]->Init(
this))
442 AddWrappedFunctionName(wrappers_[i]->GetFuncName());
453 const char* version_string =
454 reinterpret_cast<const char*
>(GetString(GL_VERSION));
455 if (version_string) {
456 std::string version(version_string);
457 gl_version_string_ = version;
458 if (version.find(
"WebGL") != std::string::npos) {
460 gl_api_standard_ =
kWeb;
461 }
else if (version.find(
"GL ES") != std::string::npos ||
462 version.find(
"GL/ES") != std::string::npos ||
463 version.find(
"GL / ES") != std::string::npos) {
464 gl_api_standard_ =
kEs;
468 const size_t dot_pos = version.find(
'.');
469 if (dot_pos != std::string::npos && dot_pos > 0U) {
472 major = version[dot_pos - 1U] -
'0';
473 minor = version[dot_pos + 1U] -
'0';
474 gl_version_ = major * 10U + minor;
478 if (
const char* renderer_string =
479 reinterpret_cast<const char*>(GetString(GL_RENDERER)))
480 gl_renderer_ = renderer_string;
483 GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
488 if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
491 if (
const char* extensions =
492 reinterpret_cast<const char*>(GetString(GL_EXTENSIONS)))
493 extensions_ = extensions;
496 valid_statetable_caps_.reset();
497 valid_statetable_caps_.flip();
507 "debug_output,debug",
"");
509 "framebuffer_blit",
"");
512 "framebuffer_multisample",
"");
519 "mapbuffer,vertex_buffer_object",
520 "Vivante GC1000,VideoCore IV HW");
523 "Vivante GC1000,VideoCore IV HW");
525 "sampler_objects",
"Mali ,Mali-");
529 "texture_multisample",
"");
531 "texture_storage",
"");
534 "texture_storage_multisample",
"");
536 "vertex_array_object",
"Internet Explorer");
538 "instanced_drawing",
"");
542 "transform_feedback",
"");
546 GetIntegerv(GL_NUM_EXTENSIONS, &count);
547 std::vector<std::string> extension_list;
549 if (
const char* extension =
550 reinterpret_cast<const char*>(GetStringi(GL_EXTENSIONS, i))) {
551 extension_list.push_back(std::string(extension));
566 DeleteVertexArrays(1U, &
id);
576 switch (error_code) {
577 case GL_INVALID_ENUM:
return "invalid enumerant";
578 case GL_INVALID_VALUE:
return "invalid value";
579 case GL_INVALID_OPERATION:
return "invalid operation";
580 case GL_OUT_OF_MEMORY:
return "out of memory";
581 case GL_INVALID_FRAMEBUFFER_OPERATION:
582 return "invalid framebuffer operation";
583 default:
return "unknown error";
588 const size_t num_wrappers = wrappers_.size();
590 for (
size_t i = 0; i < num_wrappers; ++i)
591 wrappers_[i]->Reset();
592 wrapped_function_names_.clear();
593 if (function_groups_.size() > 0) {
594 function_groups_.clear();
600 void GraphicsManager::CheckForErrors(
const char* when,
601 const std::string& func_call) {
604 if (func_call.find(
"GetError") == std::string::npos) {
605 GLenum error = this->GetError();
606 if (error != GL_NO_ERROR) {
607 if (tracing_ostream_) {
608 *tracing_ostream_ <<
"*** GL error " << when <<
" call to "
609 << func_call <<
": " <<
ErrorString(error) <<
"\n";
611 LOG(
ERROR) <<
"*** GL error " << when <<
" call to "
612 << func_call <<
": " <<
ErrorString(error) <<
"\n";
617 void* GraphicsManager::Lookup(
const char* name,
bool is_core) {
623 const std::string& extensions,
const std::string& disabled_renderers) {
626 const std::vector<std::string> renderers =
628 const size_t renderer_count = renderers.size();
630 for (
size_t i = 0; i < renderer_count; ++i) {
631 if (gl_renderer_.find(renderers[i]) != std::string::npos) {
638 const size_t count = names.size();
641 for (
size_t i = 0; i <
count; ++i) {
648 if (versions[gl_api_standard_] && gl_version_ >= versions[gl_api_standard_])
652 for (
size_t i = 0; i <
count; ++i) {
GraphicsManager manages the graphics library for an application.
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
See https://www.opengl.org/registry/specs/EXT/gpu_shader4.txt.
Capability
GraphicsManager supports queries on local GL platform capabilities, such as the maximum texture size ...
const T & Get() const
If this contains an object of type T (which must be one of the defined types), this returns a const r...
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei count
bool IsFunctionGroupAvailable(FunctionGroupId group) const
Returns true if the named function group is available. Thread-safe.
~GraphicsManager() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
ION_API bool IsExtensionIncomplete(const char *unprefixed_extension)
Returns whether the passed extension is known to be incomplete for the current platform.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei GLuint shaders value
Range< 1, int32 > Range1i
Simple wrapper for a set of GL versions.
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
#define ION_DOUBLE_CAP(index, enum1, enum2, getter)
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
void InitGlInfo()
Initializes local GL information such as version and platform api standard.
Information about shader precision, see below.
framebuffer alpha dfactor const GLvoid usage alpha GLint
The below are returned as a ShaderPrecision struct.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei GLuint shaders GLint data GLsizei GLchar info_log GLint params GLint GLint precision GLint params GLint params GLint params GLfloat params GLvoid pointer height height const GLchar const GLint length mask dppass param param const GLvoid data const GLint1 value const GLfloat2 value v2 v2 v3 v3 const GLmatrix2 value const GLmatrix4 value v1 v2 v3 const GLvoid pointer GLsizei GLchar label const GLchar marker const void userParam const GLchar buf void params height const GLuint1 value const GLuint2 value const GLuint3 value const GLuint4 value void image primCount divisor length size sampler GLuint samplers GLint params const GLfloat params const GLint params flags timeout const GLvoid data const GLvoid pixels fixed_sample_locations GLfloat val height fixed_sample_locations primitive_mode const GLuint ids GLsizei GLsizei GLenum GLchar name const GLchar buffer_mode GenVertexArrays
void * GetGlProcAddress(const char *name, bool is_core)
Returns a generic pointer to an OpenGL function or OpenGL extension function with the given name...
bool IsExtensionSupported(const std::string &name) const
Checks if the passed extension is supported by this manager.
static const char * ErrorString(GLenum error_code)
Returns a terse string description of an OpenGL error code.
ION_API bool IsExtensionSupported(const std::string &unprefixed_extension, const std::string &extensions_string)
Returns whether the currently bound OpenGL implementation supports the named extension.
void ReinitFunctions()
This is used by MockGraphicsManager to install its own versions of the OpenGL functions.
GraphicsManager()
GraphicsManager implementation.
#define ION_SINGLE_CAP(index, enum, getter)
This covers both OES_EGL_image and OES_EGL_image_external.
std::string JoinStrings(const std::vector< std::string > &strings, const std::string &glue)
Joins the strings in the passed vector together with the passed glue.
Copyright 2016 Google Inc.
virtual void EnableFunctionGroupIfAvailable(FunctionGroupId group, const GlVersions &versions, const std::string &extensions, const std::string &disabled_renderers)
Verifies that a function group is available by checking if the GL version for the current API is high...
const AllocatorPtr & GetAllocator() const
Returns the Allocator that was used for the instance.
const T GetCapabilityValue(Capability cap)
Returns the value of the passed Capability.
void EnableFunctionGroup(FunctionGroupId group, bool enable)
Enables or disables a specific function group.
Range< 1, float > Range1f