Index: ui/gl/gl_gl_api_implementation.cc |
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc |
index 265bd31f2bc2b86b83c0a4bd79bc1ceaf372cf25..cc4453ea910464274308768dfb8a9dcc9e77dc71 100644 |
--- a/ui/gl/gl_gl_api_implementation.cc |
+++ b/ui/gl/gl_gl_api_implementation.cc |
@@ -7,6 +7,7 @@ |
#include <vector> |
#include "base/command_line.h" |
+#include "base/memory/ptr_util.h" |
#include "base/stl_util.h" |
#include "base/strings/string_split.h" |
#include "base/strings/string_util.h" |
@@ -19,28 +20,25 @@ |
namespace gl { |
-// The GL Api being used. This could be g_real_gl or gl_trace_gl |
-static GLApi* g_gl = NULL; |
-// A GL Api that calls directly into the driver. |
-static RealGLApi* g_real_gl = NULL; |
-// A GL Api that does nothing but warn about illegal GL calls without a context |
-// current. |
-static NoContextGLApi* g_no_context_gl = NULL; |
-// A GL Api that calls TRACE and then calls another GL api. |
-static TraceGLApi* g_trace_gl = NULL; |
-// The GL Api being used for stub contexts. If null, g_gl is used instead. |
-static GLApi* g_stub_gl = NULL; |
-// GL version used when initializing dynamic bindings. |
-static GLVersionInfo* g_version_info = NULL; |
+// The GL state for when no context is bound |
+static CurrentGL* g_no_context_current_gl = nullptr; |
+ |
+// If the null draw bindings are currently enabled. |
+// TODO: Consider adding a new GLApi that no-ops these functions |
+static bool g_null_draw_bindings_enabled = false; |
+ |
+// If the GL debug bindings are enabled. |
+static bool g_debug_bindings_enabled = false; |
namespace { |
-static inline GLenum GetInternalFormat(GLenum internal_format) { |
- if (!g_version_info->is_es) { |
+static inline GLenum GetInternalFormat(const GLVersionInfo* version, |
+ GLenum internal_format) { |
+ if (!version->is_es) { |
if (internal_format == GL_BGRA_EXT || internal_format == GL_BGRA8_EXT) |
return GL_RGBA8; |
} |
- if (g_version_info->is_es3 && g_version_info->is_mesa) { |
+ if (version->is_es3 && version->is_mesa) { |
// Mesa bug workaround: Mipmapping does not work when using GL_BGRA_EXT |
if (internal_format == GL_BGRA_EXT) |
return GL_RGBA; |
@@ -49,14 +47,14 @@ static inline GLenum GetInternalFormat(GLenum internal_format) { |
} |
// TODO(epenner): Could the above function be merged into this and removed? |
-static inline GLenum GetTexInternalFormat(GLenum internal_format, |
+static inline GLenum GetTexInternalFormat(const GLVersionInfo* version, |
+ GLenum internal_format, |
GLenum format, |
GLenum type) { |
- DCHECK(g_version_info); |
- GLenum gl_internal_format = GetInternalFormat(internal_format); |
+ GLenum gl_internal_format = GetInternalFormat(version, internal_format); |
// g_version_info must be initialized when this function is bound. |
- if (g_version_info->is_es3) { |
+ if (version->is_es3) { |
if (internal_format == GL_RED_EXT) { |
// GL_EXT_texture_rg case in ES2. |
switch (type) { |
@@ -94,8 +92,8 @@ static inline GLenum GetTexInternalFormat(GLenum internal_format, |
} |
} |
- if (type == GL_FLOAT && g_version_info->is_angle && g_version_info->is_es && |
- g_version_info->major_version == 2) { |
+ if (type == GL_FLOAT && version->is_angle && version->is_es && |
+ version->major_version == 2) { |
// It's possible that the texture is using a sized internal format, and |
// ANGLE exposing GLES2 API doesn't support those. |
// TODO(oetuaho@nvidia.com): Remove these conversions once ANGLE has the |
@@ -113,8 +111,7 @@ static inline GLenum GetTexInternalFormat(GLenum internal_format, |
} |
} |
- if (g_version_info->IsAtLeastGL(2, 1) || |
- g_version_info->IsAtLeastGLES(3, 0)) { |
+ if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) { |
switch (internal_format) { |
case GL_SRGB_EXT: |
gl_internal_format = GL_SRGB8; |
@@ -127,7 +124,7 @@ static inline GLenum GetTexInternalFormat(GLenum internal_format, |
} |
} |
- if (g_version_info->is_es) |
+ if (version->is_es) |
return gl_internal_format; |
if (type == GL_FLOAT) { |
@@ -195,12 +192,10 @@ static inline GLenum GetTexInternalFormat(GLenum internal_format, |
return gl_internal_format; |
} |
-static inline GLenum GetTexFormat(GLenum format) { |
+static inline GLenum GetTexFormat(const GLVersionInfo* version, GLenum format) { |
GLenum gl_format = format; |
- DCHECK(g_version_info); |
- if (g_version_info->IsAtLeastGL(2, 1) || |
- g_version_info->IsAtLeastGLES(3, 0)) { |
+ if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) { |
switch (format) { |
case GL_SRGB_EXT: |
gl_format = GL_RGB; |
@@ -216,271 +211,64 @@ static inline GLenum GetTexFormat(GLenum format) { |
return gl_format; |
} |
-static inline GLenum GetTexType(GLenum type) { |
- if (!g_version_info->is_es) { |
+static inline GLenum GetTexType(const GLVersionInfo* version, GLenum type) { |
+ if (!version->is_es) { |
if (type == GL_HALF_FLOAT_OES) |
return GL_HALF_FLOAT_ARB; |
} |
return type; |
} |
-static void GL_BINDING_CALL CustomTexImage2D( |
- GLenum target, GLint level, GLint internalformat, |
- GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, |
- const void* pixels) { |
- GLenum gl_internal_format = GetTexInternalFormat( |
- internalformat, format, type); |
- GLenum gl_format = GetTexFormat(format); |
- GLenum gl_type = GetTexType(type); |
- g_driver_gl.orig_fn.glTexImage2DFn( |
- target, level, gl_internal_format, width, height, border, gl_format, |
- gl_type, pixels); |
-} |
- |
-static void GL_BINDING_CALL CustomTexSubImage2D( |
- GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, |
- GLsizei height, GLenum format, GLenum type, const void* pixels) { |
- GLenum gl_format = GetTexFormat(format); |
- GLenum gl_type = GetTexType(type); |
- g_driver_gl.orig_fn.glTexSubImage2DFn( |
- target, level, xoffset, yoffset, width, height, gl_format, gl_type, |
- pixels); |
-} |
- |
-static void GL_BINDING_CALL CustomTexStorage2DEXT( |
- GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, |
- GLsizei height) { |
- GLenum gl_internal_format = GetInternalFormat(internalformat); |
- g_driver_gl.orig_fn.glTexStorage2DEXTFn( |
- target, levels, gl_internal_format, width, height); |
-} |
- |
-static void GL_BINDING_CALL CustomRenderbufferStorageEXT( |
- GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { |
- GLenum gl_internal_format = GetInternalFormat(internalformat); |
- g_driver_gl.orig_fn.glRenderbufferStorageEXTFn( |
- target, gl_internal_format, width, height); |
-} |
- |
-// The ANGLE and IMG variants of glRenderbufferStorageMultisample currently do |
-// not support BGRA render buffers so only the EXT one is customized. If |
-// GL_CHROMIUM_renderbuffer_format_BGRA8888 support is added to ANGLE then the |
-// ANGLE version should also be customized. |
-static void GL_BINDING_CALL CustomRenderbufferStorageMultisampleEXT( |
- GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, |
- GLsizei height) { |
- GLenum gl_internal_format = GetInternalFormat(internalformat); |
- g_driver_gl.orig_fn.glRenderbufferStorageMultisampleEXTFn( |
- target, samples, gl_internal_format, width, height); |
-} |
- |
-static void GL_BINDING_CALL |
-CustomRenderbufferStorageMultisample(GLenum target, |
- GLsizei samples, |
- GLenum internalformat, |
- GLsizei width, |
- GLsizei height) { |
- GLenum gl_internal_format = GetInternalFormat(internalformat); |
- g_driver_gl.orig_fn.glRenderbufferStorageMultisampleFn( |
- target, samples, gl_internal_format, width, height); |
-} |
- |
} // anonymous namespace |
-void DriverGL::InitializeCustomDynamicBindings(GLContext* context) { |
- InitializeDynamicBindings(context); |
- |
- DCHECK(orig_fn.glTexImage2DFn == NULL); |
- orig_fn.glTexImage2DFn = fn.glTexImage2DFn; |
- fn.glTexImage2DFn = |
- reinterpret_cast<glTexImage2DProc>(CustomTexImage2D); |
- |
- DCHECK(orig_fn.glTexSubImage2DFn == NULL); |
- orig_fn.glTexSubImage2DFn = fn.glTexSubImage2DFn; |
- fn.glTexSubImage2DFn = |
- reinterpret_cast<glTexSubImage2DProc>(CustomTexSubImage2D); |
- |
- DCHECK(orig_fn.glTexStorage2DEXTFn == NULL); |
- orig_fn.glTexStorage2DEXTFn = fn.glTexStorage2DEXTFn; |
- fn.glTexStorage2DEXTFn = |
- reinterpret_cast<glTexStorage2DEXTProc>(CustomTexStorage2DEXT); |
- |
- DCHECK(orig_fn.glRenderbufferStorageEXTFn == NULL); |
- orig_fn.glRenderbufferStorageEXTFn = fn.glRenderbufferStorageEXTFn; |
- fn.glRenderbufferStorageEXTFn = |
- reinterpret_cast<glRenderbufferStorageEXTProc>( |
- CustomRenderbufferStorageEXT); |
- |
- DCHECK(orig_fn.glRenderbufferStorageMultisampleEXTFn == NULL); |
- orig_fn.glRenderbufferStorageMultisampleEXTFn = |
- fn.glRenderbufferStorageMultisampleEXTFn; |
- fn.glRenderbufferStorageMultisampleEXTFn = |
- reinterpret_cast<glRenderbufferStorageMultisampleEXTProc>( |
- CustomRenderbufferStorageMultisampleEXT); |
- |
- DCHECK(orig_fn.glRenderbufferStorageMultisampleFn == NULL); |
- orig_fn.glRenderbufferStorageMultisampleFn = |
- fn.glRenderbufferStorageMultisampleFn; |
- fn.glRenderbufferStorageMultisampleFn = |
- reinterpret_cast<glRenderbufferStorageMultisampleProc>( |
- CustomRenderbufferStorageMultisample); |
-} |
- |
-static void GL_BINDING_CALL NullDrawClearFn(GLbitfield mask) { |
- if (!g_driver_gl.null_draw_bindings_enabled) |
- g_driver_gl.orig_fn.glClearFn(mask); |
-} |
- |
-static void GL_BINDING_CALL |
-NullDrawDrawArraysFn(GLenum mode, GLint first, GLsizei count) { |
- if (!g_driver_gl.null_draw_bindings_enabled) |
- g_driver_gl.orig_fn.glDrawArraysFn(mode, first, count); |
-} |
- |
-static void GL_BINDING_CALL NullDrawDrawElementsFn(GLenum mode, |
- GLsizei count, |
- GLenum type, |
- const void* indices) { |
- if (!g_driver_gl.null_draw_bindings_enabled) |
- g_driver_gl.orig_fn.glDrawElementsFn(mode, count, type, indices); |
-} |
- |
-void DriverGL::InitializeNullDrawBindings() { |
- DCHECK(orig_fn.glClearFn == NULL); |
- orig_fn.glClearFn = fn.glClearFn; |
- fn.glClearFn = NullDrawClearFn; |
- |
- DCHECK(orig_fn.glDrawArraysFn == NULL); |
- orig_fn.glDrawArraysFn = fn.glDrawArraysFn; |
- fn.glDrawArraysFn = NullDrawDrawArraysFn; |
- |
- DCHECK(orig_fn.glDrawElementsFn == NULL); |
- orig_fn.glDrawElementsFn = fn.glDrawElementsFn; |
- fn.glDrawElementsFn = NullDrawDrawElementsFn; |
- |
- null_draw_bindings_enabled = true; |
-} |
- |
-bool DriverGL::HasInitializedNullDrawBindings() { |
- return orig_fn.glClearFn != NULL && orig_fn.glDrawArraysFn != NULL && |
- orig_fn.glDrawElementsFn != NULL; |
-} |
- |
-bool DriverGL::SetNullDrawBindingsEnabled(bool enabled) { |
- DCHECK(orig_fn.glClearFn != NULL); |
- DCHECK(orig_fn.glDrawArraysFn != NULL); |
- DCHECK(orig_fn.glDrawElementsFn != NULL); |
- |
- bool before = null_draw_bindings_enabled; |
- null_draw_bindings_enabled = enabled; |
- return before; |
-} |
- |
void InitializeStaticGLBindingsGL() { |
- g_current_gl_context_tls = new base::ThreadLocalPointer<GLApi>; |
- g_driver_gl.InitializeStaticBindings(); |
- if (!g_real_gl) { |
- g_real_gl = new RealGLApi(); |
- g_trace_gl = new TraceGLApi(g_real_gl); |
- g_no_context_gl = new NoContextGLApi(); |
- } |
- g_real_gl->Initialize(&g_driver_gl); |
- g_gl = g_real_gl; |
- if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableGPUServiceTracing)) { |
- g_gl = g_trace_gl; |
- } |
- SetGLToRealGLApi(); |
-} |
- |
-GLApi* GetCurrentGLApi() { |
- return g_current_gl_context_tls ? g_current_gl_context_tls->Get() : nullptr; |
-} |
- |
-void SetGLApi(GLApi* api) { |
- g_current_gl_context_tls->Set(api); |
-} |
- |
-void SetGLToRealGLApi() { |
- SetGLApi(g_gl); |
-} |
- |
-void SetGLToStubGLApi() { |
- SetGLApi(g_stub_gl ? g_stub_gl : g_gl); |
-} |
- |
-void SetGLApiToNoContext() { |
- SetGLApi(g_no_context_gl); |
-} |
- |
-void SetStubGLApi(GLApi* api) { |
- g_stub_gl = api; |
+ g_current_gl_context_tls = new base::ThreadLocalPointer<CurrentGL>; |
+ g_no_context_current_gl = new CurrentGL; |
+ g_no_context_current_gl->Api = new NoContextGLApi; |
} |
-const GLVersionInfo* GetGLVersionInfo() { |
- return g_version_info; |
-} |
+void ClearBindingsGL() { |
+ if (g_no_context_current_gl) { |
+ delete g_no_context_current_gl->Api; |
+ delete g_no_context_current_gl->Driver; |
+ delete g_no_context_current_gl->Version; |
+ delete g_no_context_current_gl; |
+ g_no_context_current_gl = nullptr; |
+ } |
-void InitializeDynamicGLBindingsGL(GLContext* context) { |
- if (g_version_info) |
- return; |
- g_real_gl->InitializeFilteredExtensions(); |
- g_driver_gl.InitializeCustomDynamicBindings(context); |
- DCHECK(context && context->IsCurrent(NULL) && !g_version_info); |
- g_version_info = new GLVersionInfo( |
- context->GetGLVersion().c_str(), |
- context->GetGLRenderer().c_str(), |
- context->GetExtensions().c_str()); |
+ if (g_current_gl_context_tls) { |
+ delete g_current_gl_context_tls; |
+ g_current_gl_context_tls = nullptr; |
+ } |
} |
void InitializeDebugGLBindingsGL() { |
- g_driver_gl.InitializeDebugBindings(); |
+ g_debug_bindings_enabled = true; |
} |
-void InitializeNullDrawGLBindingsGL() { |
- g_driver_gl.InitializeNullDrawBindings(); |
+bool GetDebugGLBindingsInitializedGL() { |
+ return g_debug_bindings_enabled; |
} |
-bool HasInitializedNullDrawGLBindingsGL() { |
- return g_driver_gl.HasInitializedNullDrawBindings(); |
+bool SetNullDrawGLBindingsEnabled(bool enabled) { |
+ bool old_value = g_null_draw_bindings_enabled; |
+ g_null_draw_bindings_enabled = enabled; |
+ return old_value; |
} |
-bool SetNullDrawGLBindingsEnabledGL(bool enabled) { |
- return g_driver_gl.SetNullDrawBindingsEnabled(enabled); |
+bool GetNullDrawBindingsEnabled() { |
+ return g_null_draw_bindings_enabled; |
} |
-void ClearBindingsGL() { |
- if (g_real_gl) { |
- delete g_real_gl; |
- g_real_gl = NULL; |
- } |
- if (g_trace_gl) { |
- delete g_trace_gl; |
- g_trace_gl = NULL; |
- } |
- if (g_no_context_gl) { |
- delete g_no_context_gl; |
- g_no_context_gl = NULL; |
- } |
- g_gl = NULL; |
- g_stub_gl = NULL; |
- g_driver_gl.ClearBindings(); |
- if (g_current_gl_context_tls) { |
- delete g_current_gl_context_tls; |
- g_current_gl_context_tls = NULL; |
- } |
- if (g_version_info) { |
- delete g_version_info; |
- g_version_info = NULL; |
- } |
+void SetCurrentGL(CurrentGL* current) { |
+ CurrentGL* new_current = current ? current : g_no_context_current_gl; |
+ g_current_gl_context_tls->Set(new_current); |
} |
GLApi::GLApi() { |
} |
GLApi::~GLApi() { |
- if (GetCurrentGLApi() == this) |
- SetGLApi(NULL); |
} |
GLApiBase::GLApiBase() |
@@ -555,10 +343,121 @@ const GLubyte* RealGLApi::glGetStringiFn(GLenum name, GLuint index) { |
return GLApiBase::glGetStringiFn(name, index); |
} |
+void RealGLApi::glTexImage2DFn(GLenum target, |
+ GLint level, |
+ GLint internalformat, |
+ GLsizei width, |
+ GLsizei height, |
+ GLint border, |
+ GLenum format, |
+ GLenum type, |
+ const void* pixels) { |
+ GLenum gl_internal_format = |
+ GetTexInternalFormat(version_.get(), internalformat, format, type); |
+ GLenum gl_format = GetTexFormat(version_.get(), format); |
+ GLenum gl_type = GetTexType(version_.get(), type); |
+ GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width, height, |
+ border, gl_format, gl_type, pixels); |
+} |
+ |
+void RealGLApi::glTexSubImage2DFn(GLenum target, |
+ GLint level, |
+ GLint xoffset, |
+ GLint yoffset, |
+ GLsizei width, |
+ GLsizei height, |
+ GLenum format, |
+ GLenum type, |
+ const void* pixels) { |
+ GLenum gl_format = GetTexFormat(version_.get(), format); |
+ GLenum gl_type = GetTexType(version_.get(), type); |
+ GLApiBase::glTexSubImage2DFn(target, level, xoffset, yoffset, width, height, |
+ gl_format, gl_type, pixels); |
+} |
+ |
+void RealGLApi::glTexStorage2DEXTFn(GLenum target, |
+ GLsizei levels, |
+ GLenum internalformat, |
+ GLsizei width, |
+ GLsizei height) { |
+ GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat); |
+ GLApiBase::glTexStorage2DEXTFn(target, levels, gl_internal_format, width, |
+ height); |
+} |
+ |
+void RealGLApi::glRenderbufferStorageEXTFn(GLenum target, |
+ GLenum internalformat, |
+ GLsizei width, |
+ GLsizei height) { |
+ GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat); |
+ GLApiBase::glRenderbufferStorageEXTFn(target, gl_internal_format, width, |
+ height); |
+} |
+ |
+// The ANGLE and IMG variants of glRenderbufferStorageMultisample currently do |
+// not support BGRA render buffers so only the EXT one is customized. If |
+// GL_CHROMIUM_renderbuffer_format_BGRA8888 support is added to ANGLE then the |
+// ANGLE version should also be customized. |
+void RealGLApi::glRenderbufferStorageMultisampleEXTFn(GLenum target, |
+ GLsizei samples, |
+ GLenum internalformat, |
+ GLsizei width, |
+ GLsizei height) { |
+ GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat); |
+ GLApiBase::glRenderbufferStorageMultisampleEXTFn( |
+ target, samples, gl_internal_format, width, height); |
+} |
+ |
+void RealGLApi::glRenderbufferStorageMultisampleFn(GLenum target, |
+ GLsizei samples, |
+ GLenum internalformat, |
+ GLsizei width, |
+ GLsizei height) { |
+ GLenum gl_internal_format = GetInternalFormat(version_.get(), internalformat); |
+ GLApiBase::glRenderbufferStorageMultisampleFn( |
+ target, samples, gl_internal_format, width, height); |
+} |
+ |
+void RealGLApi::glClearFn(GLbitfield mask) { |
+ if (!g_null_draw_bindings_enabled) |
+ GLApiBase::glClearFn(mask); |
+} |
+ |
+void RealGLApi::glDrawArraysFn(GLenum mode, GLint first, GLsizei count) { |
+ if (!g_null_draw_bindings_enabled) |
+ GLApiBase::glDrawArraysFn(mode, first, count); |
+} |
+ |
+void RealGLApi::glDrawElementsFn(GLenum mode, |
+ GLsizei count, |
+ GLenum type, |
+ const void* indices) { |
+ if (!g_null_draw_bindings_enabled) |
+ GLApiBase::glDrawElementsFn(mode, count, type, indices); |
+} |
+ |
+void RealGLApi::glClearDepthFn(GLclampd depth) { |
+ if (driver_->fn.glClearDepthFn) { |
+ GLApiBase::glClearDepthFn(depth); |
+ } else { |
+ DCHECK(driver_->fn.glClearDepthfFn); |
+ GLApiBase::glClearDepthfFn(static_cast<GLclampf>(depth)); |
+ } |
+} |
+ |
+void RealGLApi::glDepthRangeFn(GLclampd z_near, GLclampd z_far) { |
+ if (driver_->fn.glDepthRangeFn) { |
+ GLApiBase::glDepthRangeFn(z_near, z_far); |
+ } else { |
+ GLApiBase::glDepthRangefFn(static_cast<GLclampf>(z_near), |
+ static_cast<GLclampf>(z_far)); |
+ } |
+} |
+ |
void RealGLApi::InitializeFilteredExtensions() { |
if (disabled_exts_.size()) { |
filtered_exts_.clear(); |
- if (WillUseGLGetStringForExtensions()) { |
+ if (WillUseGLGetStringForExtensions(this)) { |
filtered_exts_str_ = |
FilterGLExtensionList(reinterpret_cast<const char*>( |
GLApiBase::glGetStringFn(GL_EXTENSIONS)), |
@@ -583,9 +482,17 @@ void RealGLApi::InitializeFilteredExtensions() { |
} |
} |
+void RealGLApi::set_version(std::unique_ptr<GLVersionInfo> version) { |
+ version_ = std::move(version); |
+} |
+ |
TraceGLApi::~TraceGLApi() { |
} |
+DebugGLApi::DebugGLApi(GLApi* gl_api) : gl_api_(gl_api) {} |
+ |
+DebugGLApi::~DebugGLApi() {} |
+ |
NoContextGLApi::NoContextGLApi() { |
} |