summaryrefslogtreecommitdiffstats
path: root/gfx/gl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl')
-rw-r--r--gfx/gl/AndroidNativeWindow.h50
-rw-r--r--gfx/gl/AndroidSurfaceTexture.cpp197
-rw-r--r--gfx/gl/AndroidSurfaceTexture.h34
-rw-r--r--gfx/gl/AutoMappable.h148
-rw-r--r--gfx/gl/Colorspaces.cpp435
-rw-r--r--gfx/gl/Colorspaces.h987
-rw-r--r--gfx/gl/ForceDiscreteGPUHelperCGL.h34
-rw-r--r--gfx/gl/GLBlitHelper.cpp1684
-rw-r--r--gfx/gl/GLBlitHelper.h338
-rw-r--r--gfx/gl/GLBlitHelperD3D.cpp399
-rw-r--r--gfx/gl/GLConsts.h7204
-rwxr-xr-xgfx/gl/GLConsts.py175
-rw-r--r--gfx/gl/GLContext.cpp2652
-rw-r--r--gfx/gl/GLContext.h3883
-rw-r--r--gfx/gl/GLContextCGL.h80
-rw-r--r--gfx/gl/GLContextEAGL.h74
-rw-r--r--gfx/gl/GLContextEGL.h166
-rw-r--r--gfx/gl/GLContextFeatures.cpp642
-rw-r--r--gfx/gl/GLContextGLX.h87
-rw-r--r--gfx/gl/GLContextProvider.h94
-rw-r--r--gfx/gl/GLContextProviderCGL.mm368
-rw-r--r--gfx/gl/GLContextProviderEAGL.mm225
-rw-r--r--gfx/gl/GLContextProviderEGL.cpp1261
-rw-r--r--gfx/gl/GLContextProviderGLX.cpp908
-rw-r--r--gfx/gl/GLContextProviderImpl.h59
-rw-r--r--gfx/gl/GLContextProviderLinux.cpp69
-rw-r--r--gfx/gl/GLContextProviderNull.cpp30
-rw-r--r--gfx/gl/GLContextProviderWGL.cpp529
-rw-r--r--gfx/gl/GLContextSymbols.h467
-rw-r--r--gfx/gl/GLContextTypes.h60
-rw-r--r--gfx/gl/GLContextWGL.h61
-rw-r--r--gfx/gl/GLDebugUtils.cpp60
-rw-r--r--gfx/gl/GLDebugUtils.h19
-rw-r--r--gfx/gl/GLDefs.h110
-rw-r--r--gfx/gl/GLLibraryEGL.cpp1079
-rw-r--r--gfx/gl/GLLibraryEGL.h993
-rw-r--r--gfx/gl/GLLibraryLoader.cpp74
-rw-r--r--gfx/gl/GLLibraryLoader.h52
-rw-r--r--gfx/gl/GLReadTexImageHelper.cpp628
-rw-r--r--gfx/gl/GLReadTexImageHelper.h85
-rw-r--r--gfx/gl/GLScreenBuffer.cpp147
-rw-r--r--gfx/gl/GLScreenBuffer.h87
-rw-r--r--gfx/gl/GLTextureImage.cpp453
-rw-r--r--gfx/gl/GLTextureImage.h288
-rw-r--r--gfx/gl/GLTypes.h115
-rw-r--r--gfx/gl/GLUploadHelpers.cpp518
-rw-r--r--gfx/gl/GLUploadHelpers.h77
-rw-r--r--gfx/gl/GLXLibrary.h285
-rw-r--r--gfx/gl/GfxTexturesReporter.cpp77
-rw-r--r--gfx/gl/GfxTexturesReporter.h96
-rw-r--r--gfx/gl/HeapCopyOfStackArray.h44
-rw-r--r--gfx/gl/MozFramebuffer.cpp225
-rw-r--r--gfx/gl/MozFramebuffer.h109
-rw-r--r--gfx/gl/ScopedGLHelpers.cpp490
-rw-r--r--gfx/gl/ScopedGLHelpers.h260
-rw-r--r--gfx/gl/SharedSurface.cpp153
-rw-r--r--gfx/gl/SharedSurface.h199
-rw-r--r--gfx/gl/SharedSurfaceANGLE.cpp215
-rw-r--r--gfx/gl/SharedSurfaceANGLE.h75
-rw-r--r--gfx/gl/SharedSurfaceAndroidHardwareBuffer.cpp168
-rw-r--r--gfx/gl/SharedSurfaceAndroidHardwareBuffer.h70
-rw-r--r--gfx/gl/SharedSurfaceD3D11Interop.cpp489
-rw-r--r--gfx/gl/SharedSurfaceD3D11Interop.h84
-rw-r--r--gfx/gl/SharedSurfaceDMABUF.cpp142
-rw-r--r--gfx/gl/SharedSurfaceDMABUF.h69
-rw-r--r--gfx/gl/SharedSurfaceEGL.cpp269
-rw-r--r--gfx/gl/SharedSurfaceEGL.h130
-rw-r--r--gfx/gl/SharedSurfaceGL.cpp42
-rw-r--r--gfx/gl/SharedSurfaceGL.h42
-rw-r--r--gfx/gl/SharedSurfaceIO.cpp103
-rw-r--r--gfx/gl/SharedSurfaceIO.h64
-rw-r--r--gfx/gl/SurfaceTypes.h35
-rw-r--r--gfx/gl/WGLLibrary.h114
-rw-r--r--gfx/gl/gtest/TestColorspaces.cpp698
-rw-r--r--gfx/gl/gtest/moz.build15
-rw-r--r--gfx/gl/moz.build163
76 files changed, 33110 insertions, 0 deletions
diff --git a/gfx/gl/AndroidNativeWindow.h b/gfx/gl/AndroidNativeWindow.h
new file mode 100644
index 0000000000..a45fccc099
--- /dev/null
+++ b/gfx/gl/AndroidNativeWindow.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AndroidNativeWindow_h__
+#define AndroidNativeWindow_h__
+
+#include <jni.h>
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+#include "mozilla/java/GeckoSurfaceWrappers.h"
+#include "SurfaceTexture.h"
+
+namespace mozilla {
+namespace gl {
+
+class AndroidNativeWindow final {
+ public:
+ AndroidNativeWindow() : mNativeWindow(nullptr) {}
+
+ explicit AndroidNativeWindow(java::sdk::Surface::Param aSurface) {
+ mNativeWindow =
+ ANativeWindow_fromSurface(jni::GetEnvForThread(), aSurface.Get());
+ }
+
+ explicit AndroidNativeWindow(java::GeckoSurface::Param aSurface) {
+ java::sdk::Surface::LocalRef surf = aSurface->GetSurface();
+ mNativeWindow =
+ ANativeWindow_fromSurface(jni::GetEnvForThread(), surf.Get());
+ }
+
+ ~AndroidNativeWindow() {
+ if (mNativeWindow) {
+ ANativeWindow_release(mNativeWindow);
+ mNativeWindow = nullptr;
+ }
+ }
+
+ ANativeWindow* NativeWindow() const { return mNativeWindow; }
+
+ private:
+ ANativeWindow* mNativeWindow;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // AndroidNativeWindow_h__
diff --git a/gfx/gl/AndroidSurfaceTexture.cpp b/gfx/gl/AndroidSurfaceTexture.cpp
new file mode 100644
index 0000000000..30260efe32
--- /dev/null
+++ b/gfx/gl/AndroidSurfaceTexture.cpp
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AndroidSurfaceTexture.h"
+
+#include "GLContextEGL.h"
+#include "GLBlitHelper.h"
+#include "GLImages.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/layers/LayersSurfaces.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/java/GeckoSurfaceTextureNatives.h"
+# include "AndroidNativeWindow.h"
+#endif // MOZ_WIDGET_ANDROID
+
+namespace mozilla {
+namespace gl {
+
+class AndroidSharedBlitGL final {
+ public:
+ explicit AndroidSharedBlitGL(const EGLNativeWindowType window) {
+ StaticMutexAutoLock lock(sMutex);
+
+ if (!sContext) {
+ MOZ_ASSERT(sInstanceCount == 0);
+ sContext = CreateContext();
+ if (!sContext) {
+ return;
+ }
+ }
+
+ const auto& egl = *(sContext->mEgl);
+ mTargetSurface =
+ egl.fCreateWindowSurface(sContext->mSurfaceConfig, window, nullptr);
+
+ ++sInstanceCount;
+ }
+
+ ~AndroidSharedBlitGL() {
+ StaticMutexAutoLock lock(sMutex);
+
+ if (mTargetSurface != EGL_NO_SURFACE) {
+ const auto& egl = *(sContext->mEgl);
+ egl.fDestroySurface(mTargetSurface);
+ }
+
+ // Destroy shared GL context when no one uses it.
+ if (--sInstanceCount == 0) {
+ sContext = nullptr;
+ }
+ }
+
+#ifdef MOZ_WIDGET_ANDROID
+ void Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
+ const gfx::IntSize& imageSize) {
+ StaticMutexAutoLock lock(sMutex);
+ MOZ_ASSERT(sContext);
+
+ // Setting overide also makes conext and surface current.
+ sContext->SetEGLSurfaceOverride(mTargetSurface);
+ DebugOnly<bool> rv = sContext->BlitHelper()->Blit(surfaceTexture, imageSize,
+ OriginPos::TopLeft);
+ MOZ_ASSERT(rv);
+ sContext->SwapBuffers();
+ // This method is called through binder IPC and could run on any thread in
+ // the pool. Release the context and surface from this thread after use so
+ // they can be bound to another thread later.
+ UnmakeCurrent(sContext);
+ }
+#endif
+
+ private:
+ static already_AddRefed<GLContextEGL> CreateContextImpl(bool aUseGles) {
+ sMutex.AssertCurrentThreadOwns();
+ MOZ_ASSERT(!sContext);
+
+ nsCString ignored;
+ const auto egl = gl::DefaultEglDisplay(&ignored);
+ EGLConfig eglConfig;
+ CreateConfig(*egl, &eglConfig, /* bpp */ 24, /* depth buffer? */ false,
+ aUseGles);
+ auto gl = GLContextEGL::CreateGLContext(egl, {}, eglConfig, EGL_NO_SURFACE,
+ true, eglConfig, &ignored);
+ if (!gl) {
+ NS_WARNING("Fail to create GL context for native blitter.");
+ return nullptr;
+ }
+ gl->mOwningThreadId = Nothing();
+
+ // Yield the current state made in constructor.
+ UnmakeCurrent(gl);
+ return gl.forget();
+ }
+
+ static already_AddRefed<GLContextEGL> CreateContext() {
+ RefPtr<GLContextEGL> gl;
+#if !defined(MOZ_WIDGET_ANDROID)
+ gl = CreateContextImpl(/* aUseGles */ false);
+#endif // !defined(MOZ_WIDGET_ANDROID)
+
+ if (!gl) {
+ gl = CreateContextImpl(/* aUseGles */ true);
+ }
+ return gl.forget();
+ }
+
+ static bool UnmakeCurrent(GLContextEGL* const gl) {
+ sMutex.AssertCurrentThreadOwns();
+ MOZ_ASSERT(gl);
+
+ if (!gl->IsCurrent()) {
+ return true;
+ }
+ const auto& egl = *(gl->mEgl);
+ return egl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+
+ static StaticMutex sMutex MOZ_UNANNOTATED;
+ static StaticRefPtr<GLContextEGL> sContext;
+ static size_t sInstanceCount;
+
+ EGLSurface mTargetSurface;
+};
+
+StaticMutex AndroidSharedBlitGL::sMutex;
+StaticRefPtr<GLContextEGL> AndroidSharedBlitGL::sContext;
+size_t AndroidSharedBlitGL::sInstanceCount = 0;
+
+// -
+#ifdef MOZ_WIDGET_ANDROID
+
+void AndroidSurfaceTexture::GetTransformMatrix(
+ java::sdk::SurfaceTexture::Param surfaceTexture,
+ gfx::Matrix4x4* outMatrix) {
+ JNIEnv* const env = jni::GetEnvForThread();
+
+ auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
+ surfaceTexture->GetTransformMatrix(jarray);
+
+ jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
+
+ memcpy(&(outMatrix->_11), array, sizeof(float) * 16);
+
+ env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
+}
+
+class GLBlitterSupport final
+ : public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<
+ GLBlitterSupport> {
+ public:
+ using Base =
+ java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<GLBlitterSupport>;
+ using Base::AttachNative;
+ using Base::DisposeNative;
+ using Base::GetNative;
+
+ static java::GeckoSurfaceTexture::NativeGLBlitHelper::LocalRef NativeCreate(
+ jlong sourceTextureHandle, jni::Object::Param targetSurface, jint width,
+ jint height) {
+ AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
+ auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
+ const auto& eglWindow = win.NativeWindow();
+ GLBlitterSupport::AttachNative(
+ helper,
+ MakeUnique<GLBlitterSupport>(MakeUnique<AndroidSharedBlitGL>(eglWindow),
+ sourceTextureHandle, width, height));
+ return helper;
+ }
+
+ GLBlitterSupport(UniquePtr<AndroidSharedBlitGL>&& gl,
+ jlong sourceTextureHandle, jint width, jint height)
+ : mGl(std::move(gl)),
+ mSourceTextureHandle(sourceTextureHandle),
+ mSize(width, height) {}
+
+ void Blit() {
+ auto surfaceTexture =
+ java::GeckoSurfaceTexture::Lookup(mSourceTextureHandle);
+ mGl->Blit(surfaceTexture, mSize);
+ }
+
+ private:
+ const UniquePtr<AndroidSharedBlitGL> mGl;
+ const AndroidSurfaceTextureHandle mSourceTextureHandle;
+ const gfx::IntSize mSize;
+};
+
+void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
+
+#endif // MOZ_WIDGET_ANDROID
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/AndroidSurfaceTexture.h b/gfx/gl/AndroidSurfaceTexture.h
new file mode 100644
index 0000000000..bf9a5ed6ae
--- /dev/null
+++ b/gfx/gl/AndroidSurfaceTexture.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AndroidSurfaceTexture_h__
+#define AndroidSurfaceTexture_h__
+
+#include "mozilla/gfx/Matrix.h"
+
+typedef uint64_t AndroidSurfaceTextureHandle;
+
+#ifdef MOZ_WIDGET_ANDROID
+
+# include "SurfaceTexture.h"
+
+namespace mozilla {
+namespace gl {
+
+class AndroidSurfaceTexture {
+ public:
+ static void Init();
+ static void GetTransformMatrix(
+ java::sdk::SurfaceTexture::Param surfaceTexture,
+ mozilla::gfx::Matrix4x4* outMatrix);
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // MOZ_WIDGET_ANDROID
+
+#endif // AndroidSurfaceTexture_h__
diff --git a/gfx/gl/AutoMappable.h b/gfx/gl/AutoMappable.h
new file mode 100644
index 0000000000..f93b2ccb57
--- /dev/null
+++ b/gfx/gl/AutoMappable.h
@@ -0,0 +1,148 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_AUTO_MAPPABLE_H
+#define MOZILLA_AUTO_MAPPABLE_H
+
+// Here be dragons.
+
+#include <functional>
+
+namespace mozilla::gfx {
+
+template <class T>
+size_t Hash(const T&);
+
+template <class T>
+struct StaticStdHasher {
+ static auto HashImpl(const T& v) { return std::hash<T>()(v); }
+};
+
+template <class T>
+struct StaticHasher {
+ static auto HashImpl(const T& v) { return v.hash(); }
+};
+template <class T>
+struct StaticHasher<std::optional<T>> {
+ static size_t HashImpl(const std::optional<T>& v) {
+ if (!v) return 0;
+ return Hash(*v);
+ }
+};
+template <>
+struct StaticHasher<int> : public StaticStdHasher<int> {};
+template <>
+struct StaticHasher<bool> : public StaticStdHasher<bool> {};
+template <>
+struct StaticHasher<float> : public StaticStdHasher<float> {};
+
+template <class T>
+size_t Hash(const T& v) {
+ return StaticHasher<T>::HashImpl(v);
+}
+
+//-
+// From Boost:
+// https://www.boost.org/doc/libs/1_37_0/doc/html/hash/reference.html#boost.hash_combine
+
+inline size_t HashCombine(size_t seed, const size_t hash) {
+ seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ return seed;
+}
+
+// -
+// See
+// https://codereview.stackexchange.com/questions/136770/hashing-a-tuple-in-c17
+
+template <class... Args, size_t... Ids>
+size_t HashTupleN(const std::tuple<Args...>& tup,
+ const std::index_sequence<Ids...>&) {
+ size_t seed = 0;
+ for (const auto& hash : {Hash(std::get<Ids>(tup))...}) {
+ seed = HashCombine(seed, hash);
+ }
+ return seed;
+}
+
+template <class... Args>
+size_t HashTuple(const std::tuple<Args...>& tup) {
+ return HashTupleN(tup, std::make_index_sequence<sizeof...(Args)>());
+}
+
+// -
+
+template <class T>
+auto MembersEq(const T& a, const T& b) {
+ const auto atup = a.Members();
+ const auto btup = b.Members();
+ return atup == btup;
+}
+
+template <class T>
+auto MembersLt(const T& a, const T& b) {
+ const auto atup = a.Members();
+ const auto btup = b.Members();
+ return atup == btup;
+}
+
+template <class T>
+auto MembersHash(const T& a) {
+ const auto atup = a.Members();
+ return HashTuple(atup);
+}
+
+template <class T>
+struct MembersHasher final {
+ auto operator()(const T& v) const { return v.hash(); }
+};
+
+/** E.g.:
+struct Foo {
+ int i;
+ bool b;
+
+ auto Members() const { return std::tie(i, b); }
+ INLINE_AUTO_MAPPABLE(Foo)
+};
+std::unordered_set<T, T::Hasher> easy;
+**/
+#define INLINE_DERIVE_MEMBERS_EQ(T) \
+ friend bool operator==(const T& a, const T& b) { \
+ return mozilla::gfx::MembersEq(a, b); \
+ } \
+ friend bool operator!=(const T& a, const T& b) { return !operator==(a, b); }
+#define INLINE_AUTO_MAPPABLE(T) \
+ friend bool operator<(const T& a, const T& b) { \
+ return mozilla::gfx::MembersLt(a, b); \
+ } \
+ INLINE_DERIVE_MEMBERS_EQ(T) \
+ size_t hash() const { \
+ return mozilla::gfx::MembersHash(*reinterpret_cast<const T*>(this)); \
+ } \
+ using Hasher = mozilla::gfx::MembersHasher<T>;
+
+// -
+
+/** E.g.:
+```
+struct Foo : public AutoMappable<Foo> {
+ int i;
+ bool b;
+
+ auto Members() const { return std::tie(i, b); }
+};
+std::unordered_set<T, T::Hasher> easy;
+```
+`easy.insert({{}, 2, true});`
+The initial {} is needed for aggregate initialization of AutoMappable<Foo>.
+Use INLINE_AUTO_MAPPABLE if this is too annoying.
+**/
+template <class T>
+struct AutoMappable {
+ INLINE_AUTO_MAPPABLE(T)
+};
+
+} // namespace mozilla::gfx
+
+#endif // MOZILLA_AUTO_MAPPABLE_H
diff --git a/gfx/gl/Colorspaces.cpp b/gfx/gl/Colorspaces.cpp
new file mode 100644
index 0000000000..29ddf37cd9
--- /dev/null
+++ b/gfx/gl/Colorspaces.cpp
@@ -0,0 +1,435 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// We are going to be doing so, so many transforms, so descriptive labels are
+// critical.
+
+#include "Colorspaces.h"
+
+#include "nsDebug.h"
+#include "qcms.h"
+
+namespace mozilla::color {
+
+// tf = { k * linear | linear < b
+// { a * pow(linear, 1/g) - (1-a) | linear >= b
+float TfFromLinear(const PiecewiseGammaDesc& desc, const float linear) {
+ if (linear < desc.b) {
+ return linear * desc.k;
+ }
+ float ret = linear;
+ ret = powf(ret, 1.0f / desc.g);
+ ret *= desc.a;
+ ret -= (desc.a - 1);
+ return ret;
+}
+
+float LinearFromTf(const PiecewiseGammaDesc& desc, const float tf) {
+ const auto linear_if_low = tf / desc.k;
+ if (linear_if_low < desc.b) {
+ return linear_if_low;
+ }
+ float ret = tf;
+ ret += (desc.a - 1);
+ ret /= desc.a;
+ ret = powf(ret, 1.0f * desc.g);
+ return ret;
+}
+
+// -
+
+mat3 YuvFromRgb(const YuvLumaCoeffs& yc) {
+ // Y is always [0,1]
+ // U and V are signed, and could be either [-1,+1] or [-0.5,+0.5].
+ // Specs generally use [-0.5,+0.5], so we use that too.
+ // E.g.
+ // y = 0.2126*r + 0.7152*g + 0.0722*b
+ // u = (b - y) / (u_range = u_max - u_min) // u_min = -u_max
+ // = (b - y) / (u(0,0,1) - u(1,1,0))
+ // = (b - y) / (2 * u(0,0,1))
+ // = (b - y) / (2 * u.b))
+ // = (b - y) / (2 * (1 - 0.0722))
+ // = (-0.2126*r + -0.7152*g + (1-0.0722)*b) / 1.8556
+ // v = (r - y) / 1.5748;
+ // = ((1-0.2126)*r + -0.7152*g + -0.0722*b) / 1.5748
+ const auto y = vec3({yc.r, yc.g, yc.b});
+ const auto u = vec3({0, 0, 1}) - y;
+ const auto v = vec3({1, 0, 0}) - y;
+
+ // From rows:
+ return mat3({y, u / (2 * u.z()), v / (2 * v.x())});
+}
+
+mat4 YuvFromYcbcr(const YcbcrDesc& d) {
+ // E.g.
+ // y = (yy - 16) / (235 - 16); // 16->0, 235->1
+ // u = (cb - 128) / (240 - 16); // 16->-0.5, 128->0, 240->+0.5
+ // v = (cr - 128) / (240 - 16);
+
+ const auto yRange = d.y1 - d.y0;
+ const auto uHalfRange = d.uPlusHalf - d.u0;
+ const auto uRange = 2 * uHalfRange;
+
+ const auto ycbcrFromYuv = mat4{{vec4{{yRange, 0, 0, d.y0}},
+ {{0, uRange, 0, d.u0}},
+ {{0, 0, uRange, d.u0}},
+ {{0, 0, 0, 1}}}};
+ const auto yuvFromYcbcr = inverse(ycbcrFromYuv);
+ return yuvFromYcbcr;
+}
+
+inline vec3 CIEXYZ_from_CIExyY(const vec2 xy, const float Y = 1) {
+ const auto xyz = vec3(xy, 1 - xy.x() - xy.y());
+ const auto XYZ = xyz * (Y / xy.y());
+ return XYZ;
+}
+
+mat3 XyzFromLinearRgb(const Chromaticities& c) {
+ // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+
+ // Given red (xr, yr), green (xg, yg), blue (xb, yb),
+ // and whitepoint (XW, YW, ZW)
+
+ // [ X ] [ R ]
+ // [ Y ] = M x [ G ]
+ // [ Z ] [ B ]
+
+ // [ Sr*Xr Sg*Xg Sb*Xb ]
+ // M = [ Sr*Yr Sg*Yg Sb*Yb ]
+ // [ Sr*Zr Sg*Zg Sb*Zb ]
+
+ // Xr = xr / yr
+ // Yr = 1
+ // Zr = (1 - xr - yr) / yr
+
+ // Xg = xg / yg
+ // Yg = 1
+ // Zg = (1 - xg - yg) / yg
+
+ // Xb = xb / yb
+ // Yb = 1
+ // Zb = (1 - xb - yb) / yb
+
+ // [ Sr ] [ Xr Xg Xb ]^-1 [ XW ]
+ // [ Sg ] = [ Yr Yg Yb ] x [ YW ]
+ // [ Sb ] [ Zr Zg Zb ] [ ZW ]
+
+ const auto xrgb = vec3({c.rx, c.gx, c.bx});
+ const auto yrgb = vec3({c.ry, c.gy, c.by});
+
+ const auto Xrgb = xrgb / yrgb;
+ const auto Yrgb = vec3(1);
+ const auto Zrgb = (vec3(1) - xrgb - yrgb) / yrgb;
+
+ const auto XYZrgb = mat3({Xrgb, Yrgb, Zrgb});
+ const auto XYZrgb_inv = inverse(XYZrgb);
+ const auto XYZwhitepoint = vec3({c.wx, c.wy, 1 - c.wx - c.wy}) / c.wy;
+ const auto Srgb = XYZrgb_inv * XYZwhitepoint;
+
+ const auto M = mat3({Srgb * Xrgb, Srgb * Yrgb, Srgb * Zrgb});
+ return M;
+}
+
+// -
+ColorspaceTransform ColorspaceTransform::Create(const ColorspaceDesc& src,
+ const ColorspaceDesc& dst) {
+ auto ct = ColorspaceTransform{src, dst};
+ ct.srcTf = src.tf;
+ ct.dstTf = dst.tf;
+
+ const auto RgbTfFrom = [&](const ColorspaceDesc& cs) {
+ auto rgbFrom = mat4::Identity();
+ if (cs.yuv) {
+ const auto yuvFromYcbcr = YuvFromYcbcr(cs.yuv->ycbcr);
+ const auto yuvFromRgb = YuvFromRgb(cs.yuv->yCoeffs);
+ const auto rgbFromYuv = inverse(yuvFromRgb);
+ const auto rgbFromYuv4 = mat4(rgbFromYuv);
+
+ const auto rgbFromYcbcr = rgbFromYuv4 * yuvFromYcbcr;
+ rgbFrom = rgbFromYcbcr;
+ }
+ return rgbFrom;
+ };
+
+ ct.srcRgbTfFromSrc = RgbTfFrom(src);
+ const auto dstRgbTfFromDst = RgbTfFrom(dst);
+ ct.dstFromDstRgbTf = inverse(dstRgbTfFromDst);
+
+ // -
+
+ ct.dstRgbLinFromSrcRgbLin = mat3::Identity();
+ if (!(src.chrom == dst.chrom)) {
+ const auto xyzFromSrcRgbLin = XyzFromLinearRgb(src.chrom);
+ const auto xyzFromDstRgbLin = XyzFromLinearRgb(dst.chrom);
+ const auto dstRgbLinFromXyz = inverse(xyzFromDstRgbLin);
+ ct.dstRgbLinFromSrcRgbLin = dstRgbLinFromXyz * xyzFromSrcRgbLin;
+ }
+
+ return ct;
+}
+
+vec3 ColorspaceTransform::DstFromSrc(const vec3 src) const {
+ const auto srcRgbTf = srcRgbTfFromSrc * vec4(src, 1);
+ auto srcRgbLin = srcRgbTf;
+ if (srcTf) {
+ srcRgbLin.x(LinearFromTf(*srcTf, srcRgbTf.x()));
+ srcRgbLin.y(LinearFromTf(*srcTf, srcRgbTf.y()));
+ srcRgbLin.z(LinearFromTf(*srcTf, srcRgbTf.z()));
+ }
+
+ const auto dstRgbLin = dstRgbLinFromSrcRgbLin * vec3(srcRgbLin);
+ auto dstRgbTf = dstRgbLin;
+ if (dstTf) {
+ dstRgbTf.x(TfFromLinear(*dstTf, dstRgbLin.x()));
+ dstRgbTf.y(TfFromLinear(*dstTf, dstRgbLin.y()));
+ dstRgbTf.z(TfFromLinear(*dstTf, dstRgbLin.z()));
+ }
+
+ const auto dst4 = dstFromDstRgbTf * vec4(dstRgbTf, 1);
+ return vec3(dst4);
+}
+
+// -
+
+mat3 XyzAFromXyzB_BradfordLinear(const vec2 xyA, const vec2 xyB) {
+ // This is what ICC profiles use to do whitepoint transforms,
+ // because ICC also requires D50 for the Profile Connection Space.
+
+ // From https://www.color.org/specification/ICC.1-2022-05.pdf
+ // E.3 "Linearized Bradford transformation":
+
+ const auto M_BFD = mat3{{
+ vec3{{0.8951, 0.2664f, -0.1614f}},
+ vec3{{-0.7502f, 1.7135f, 0.0367f}},
+ vec3{{0.0389f, -0.0685f, 1.0296f}},
+ }};
+ // NB: They use rho/gamma/beta, but we'll use R/G/B here.
+ const auto XYZDst = CIEXYZ_from_CIExyY(xyA); // "XYZ_W", WP of PCS
+ const auto XYZSrc = CIEXYZ_from_CIExyY(xyB); // "XYZ_NAW", WP of src
+ const auto rgbSrc = M_BFD * XYZSrc; // "RGB_SRC"
+ const auto rgbDst = M_BFD * XYZDst; // "RGB_PCS"
+ const auto rgbDstOverSrc = rgbDst / rgbSrc;
+ const auto M_dstOverSrc = mat3::Scale(rgbDstOverSrc);
+ const auto M_adapt = inverse(M_BFD) * M_dstOverSrc * M_BFD;
+ return M_adapt;
+}
+
+std::optional<mat4> ColorspaceTransform::ToMat4() const {
+ mat4 fromSrc = srcRgbTfFromSrc;
+ if (srcTf) return {};
+ fromSrc = mat4(dstRgbLinFromSrcRgbLin) * fromSrc;
+ if (dstTf) return {};
+ fromSrc = dstFromDstRgbTf * fromSrc;
+ return fromSrc;
+}
+
+Lut3 ColorspaceTransform::ToLut3(const ivec3 size) const {
+ auto lut = Lut3::Create(size);
+ lut.SetMap([&](const vec3& srcVal) { return DstFromSrc(srcVal); });
+ return lut;
+}
+
+vec3 Lut3::Sample(const vec3 in01) const {
+ const auto coord = vec3(size - 1) * in01;
+ const auto p0 = floor(coord);
+ const auto dp = coord - p0;
+ const auto ip0 = ivec3(p0);
+
+ // Trilinear
+ const auto f000 = Fetch(ip0 + ivec3({0, 0, 0}));
+ const auto f100 = Fetch(ip0 + ivec3({1, 0, 0}));
+ const auto f010 = Fetch(ip0 + ivec3({0, 1, 0}));
+ const auto f110 = Fetch(ip0 + ivec3({1, 1, 0}));
+ const auto f001 = Fetch(ip0 + ivec3({0, 0, 1}));
+ const auto f101 = Fetch(ip0 + ivec3({1, 0, 1}));
+ const auto f011 = Fetch(ip0 + ivec3({0, 1, 1}));
+ const auto f111 = Fetch(ip0 + ivec3({1, 1, 1}));
+
+ const auto fx00 = mix(f000, f100, dp.x());
+ const auto fx10 = mix(f010, f110, dp.x());
+ const auto fx01 = mix(f001, f101, dp.x());
+ const auto fx11 = mix(f011, f111, dp.x());
+
+ const auto fxy0 = mix(fx00, fx10, dp.y());
+ const auto fxy1 = mix(fx01, fx11, dp.y());
+
+ const auto fxyz = mix(fxy0, fxy1, dp.z());
+ return fxyz;
+}
+
+// -
+
+ColorProfileDesc ColorProfileDesc::From(const ColorspaceDesc& cspace) {
+ auto ret = ColorProfileDesc{};
+
+ if (cspace.yuv) {
+ const auto yuvFromYcbcr = YuvFromYcbcr(cspace.yuv->ycbcr);
+ const auto yuvFromRgb = YuvFromRgb(cspace.yuv->yCoeffs);
+ const auto rgbFromYuv = inverse(yuvFromRgb);
+ ret.rgbFromYcbcr = mat4(rgbFromYuv) * yuvFromYcbcr;
+ }
+
+ if (cspace.tf) {
+ const size_t tableSize = 256;
+ auto& tableR = ret.linearFromTf.r;
+ tableR.resize(tableSize);
+ for (size_t i = 0; i < tableR.size(); i++) {
+ const float tfVal = i / float(tableR.size() - 1);
+ const float linearVal = LinearFromTf(*cspace.tf, tfVal);
+ tableR[i] = linearVal;
+ }
+ ret.linearFromTf.g = tableR;
+ ret.linearFromTf.b = tableR;
+ }
+
+ ret.xyzd65FromLinearRgb = XyzFromLinearRgb(cspace.chrom);
+
+ return ret;
+}
+
+// -
+
+template <class T>
+constexpr inline T NewtonEstimateX(const T x1, const T y1, const T dydx,
+ const T y2 = 0) {
+ // Estimate x s.t. y=0
+ // y = y0 + x*dydx;
+ // y0 = y - x*dydx;
+ // y1 - x1*dydx = y2 - x2*dydx
+ // x2*dydx = y2 - y1 + x1*dydx
+ // x2 = (y2 - y1)/dydx + x1
+ return (y2 - y1) / dydx + x1;
+}
+
+float GuessGamma(const std::vector<float>& vals, float exp_guess) {
+ // Approximate (signed) error = 0.0.
+ constexpr float d_exp = 0.001;
+ constexpr float error_tolerance = 0.001;
+ struct Samples {
+ float y1, y2;
+ };
+ const auto Sample = [&](const float exp) {
+ int i = -1;
+ auto samples = Samples{};
+ for (const auto& expected : vals) {
+ i += 1;
+ const auto in = i / float(vals.size() - 1);
+ samples.y1 += powf(in, exp) - expected;
+ samples.y2 += powf(in, exp + d_exp) - expected;
+ }
+ samples.y1 /= vals.size(); // Normalize by val count.
+ samples.y2 /= vals.size();
+ return samples;
+ };
+ constexpr int MAX_ITERS = 10;
+ for (int i = 1;; i++) {
+ const auto err = Sample(exp_guess);
+ const auto derr = err.y2 - err.y1;
+ exp_guess = NewtonEstimateX(exp_guess, err.y1, derr / d_exp);
+ // Check if we were close before, because then this last round of estimation
+ // should get us pretty much right on it.
+ if (std::abs(err.y1) < error_tolerance) {
+ return exp_guess;
+ }
+ if (i >= MAX_ITERS) {
+ printf_stderr("GuessGamma() -> %f after %i iterations (avg err %f)\n",
+ exp_guess, i, err.y1);
+ MOZ_ASSERT(false, "GuessGamma failed.");
+ return exp_guess;
+ }
+ }
+}
+
+// -
+
+ColorProfileDesc ColorProfileDesc::From(const qcms_profile& qcmsProfile) {
+ ColorProfileDesc ret;
+
+ qcms_profile_data data = {};
+ qcms_profile_get_data(&qcmsProfile, &data);
+
+ auto xyzd50FromLinearRgb = mat3{};
+ // X contributions from [R,G,B]
+ xyzd50FromLinearRgb.at(0, 0) = data.red_colorant_xyzd50[0];
+ xyzd50FromLinearRgb.at(1, 0) = data.green_colorant_xyzd50[0];
+ xyzd50FromLinearRgb.at(2, 0) = data.blue_colorant_xyzd50[0];
+ // Y contributions from [R,G,B]
+ xyzd50FromLinearRgb.at(0, 1) = data.red_colorant_xyzd50[1];
+ xyzd50FromLinearRgb.at(1, 1) = data.green_colorant_xyzd50[1];
+ xyzd50FromLinearRgb.at(2, 1) = data.blue_colorant_xyzd50[1];
+ // Z contributions from [R,G,B]
+ xyzd50FromLinearRgb.at(0, 2) = data.red_colorant_xyzd50[2];
+ xyzd50FromLinearRgb.at(1, 2) = data.green_colorant_xyzd50[2];
+ xyzd50FromLinearRgb.at(2, 2) = data.blue_colorant_xyzd50[2];
+
+ const auto d65FromD50 = XyzAFromXyzB_BradfordLinear(D65, D50);
+ ret.xyzd65FromLinearRgb = d65FromD50 * xyzd50FromLinearRgb;
+
+ // -
+
+ const auto Fn = [&](std::vector<float>* const linearFromTf,
+ int32_t claimed_samples,
+ const qcms_color_channel channel) {
+ if (claimed_samples == 0) return; // No tf.
+
+ if (claimed_samples == -1) {
+ claimed_samples = 4096; // Ask it to generate a bunch.
+ claimed_samples = 256; // Ask it to generate a bunch.
+ }
+
+ linearFromTf->resize(AssertedCast<size_t>(claimed_samples));
+
+ const auto begin = linearFromTf->data();
+ qcms_profile_get_lut(&qcmsProfile, channel, begin,
+ begin + linearFromTf->size());
+ };
+
+ Fn(&ret.linearFromTf.r, data.linear_from_trc_red_samples,
+ qcms_color_channel::Red);
+ Fn(&ret.linearFromTf.b, data.linear_from_trc_blue_samples,
+ qcms_color_channel::Blue);
+ Fn(&ret.linearFromTf.g, data.linear_from_trc_green_samples,
+ qcms_color_channel::Green);
+
+ // -
+
+ return ret;
+}
+
+// -
+
+ColorProfileConversionDesc ColorProfileConversionDesc::From(
+ const FromDesc& desc) {
+ const auto dstLinearRgbFromXyzd65 = inverse(desc.dst.xyzd65FromLinearRgb);
+ auto ret = ColorProfileConversionDesc{
+ .srcRgbFromSrcYuv = desc.src.rgbFromYcbcr,
+ .srcLinearFromSrcTf = desc.src.linearFromTf,
+ .dstLinearFromSrcLinear =
+ dstLinearRgbFromXyzd65 * desc.src.xyzd65FromLinearRgb,
+ .dstTfFromDstLinear = {},
+ };
+ bool sameTF = true;
+ sameTF &= desc.src.linearFromTf.r == desc.dst.linearFromTf.r;
+ sameTF &= desc.src.linearFromTf.g == desc.dst.linearFromTf.g;
+ sameTF &= desc.src.linearFromTf.b == desc.dst.linearFromTf.b;
+ if (sameTF) {
+ ret.srcLinearFromSrcTf = {};
+ ret.dstTfFromDstLinear = {};
+ } else {
+ const auto Invert = [](const std::vector<float>& linearFromTf,
+ std::vector<float>* const tfFromLinear) {
+ const auto size = linearFromTf.size();
+ MOZ_ASSERT(size != 1); // Less than two is uninvertable.
+ if (size < 2) return;
+ (*tfFromLinear).resize(size);
+ InvertLut(linearFromTf, &*tfFromLinear);
+ };
+ Invert(desc.dst.linearFromTf.r, &ret.dstTfFromDstLinear.r);
+ Invert(desc.dst.linearFromTf.g, &ret.dstTfFromDstLinear.g);
+ Invert(desc.dst.linearFromTf.b, &ret.dstTfFromDstLinear.b);
+ }
+ return ret;
+}
+
+} // namespace mozilla::color
diff --git a/gfx/gl/Colorspaces.h b/gfx/gl/Colorspaces.h
new file mode 100644
index 0000000000..8f36854d2d
--- /dev/null
+++ b/gfx/gl/Colorspaces.h
@@ -0,0 +1,987 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_GL_COLORSPACES_H_
+#define MOZILLA_GFX_GL_COLORSPACES_H_
+
+// Reference: https://hackmd.io/0wkiLmP7RWOFjcD13M870A
+
+// We are going to be doing so, so many transforms, so descriptive labels are
+// critical.
+
+// Colorspace background info: https://hackmd.io/0wkiLmP7RWOFjcD13M870A
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <optional>
+#include <vector>
+
+#include "AutoMappable.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Span.h"
+
+#ifdef DEBUG
+# define ASSERT(EXPR) \
+ do { \
+ if (!(EXPR)) { \
+ __builtin_trap(); \
+ } \
+ } while (false)
+#else
+# define ASSERT(EXPR) (void)(EXPR)
+#endif
+
+struct _qcms_profile;
+typedef struct _qcms_profile qcms_profile;
+
+namespace mozilla::color {
+
+struct YuvLumaCoeffs final {
+ float r = 0.2126;
+ float g = 0.7152;
+ float b = 0.0722;
+
+ auto Members() const { return std::tie(r, g, b); }
+ INLINE_AUTO_MAPPABLE(YuvLumaCoeffs)
+
+ static constexpr auto Rec709() { return YuvLumaCoeffs(); }
+
+ static constexpr auto Rec2020() {
+ return YuvLumaCoeffs{0.2627, 0.6780, 0.0593};
+ }
+};
+
+struct PiecewiseGammaDesc final {
+ // tf = { k * linear | linear < b
+ // { a * pow(linear, 1/g) - (1-a) | linear >= b
+
+ // Default to Srgb
+ float a = 1.055;
+ float b = 0.04045 / 12.92;
+ float g = 2.4;
+ float k = 12.92;
+
+ auto Members() const { return std::tie(a, b, g, k); }
+ INLINE_AUTO_MAPPABLE(PiecewiseGammaDesc)
+
+ static constexpr auto Srgb() { return PiecewiseGammaDesc(); }
+ static constexpr auto DisplayP3() { return Srgb(); }
+
+ static constexpr auto Rec709() {
+ return PiecewiseGammaDesc{
+ 1.099,
+ 0.018,
+ 1.0 / 0.45, // ~2.222
+ 4.5,
+ };
+ }
+ // FYI: static constexpr auto Rec2020_10bit() { return Rec709(); }
+ static constexpr auto Rec2020_12bit() {
+ return PiecewiseGammaDesc{
+ 1.0993,
+ 0.0181,
+ 1.0 / 0.45, // ~2.222
+ 4.5,
+ };
+ }
+};
+
+struct YcbcrDesc final {
+ float y0 = 16 / 255.0;
+ float y1 = 235 / 255.0;
+ float u0 = 128 / 255.0;
+ float uPlusHalf = 240 / 255.0;
+
+ auto Members() const { return std::tie(y0, y1, u0, uPlusHalf); }
+ INLINE_AUTO_MAPPABLE(YcbcrDesc)
+
+ static constexpr auto Narrow8() { // AKA limited/studio/tv
+ return YcbcrDesc();
+ }
+ static constexpr auto Full8() { // AKA pc
+ return YcbcrDesc{
+ 0 / 255.0,
+ 255 / 255.0,
+ 128 / 255.0,
+ 254 / 255.0,
+ };
+ }
+ static constexpr auto Float() { // Best for a LUT
+ return YcbcrDesc{0.0, 1.0, 0.5, 1.0};
+ }
+};
+
+struct Chromaticities final {
+ float rx = 0.640;
+ float ry = 0.330;
+ float gx = 0.300;
+ float gy = 0.600;
+ float bx = 0.150;
+ float by = 0.060;
+ // D65:
+ static constexpr float wx = 0.3127;
+ static constexpr float wy = 0.3290;
+
+ auto Members() const { return std::tie(rx, ry, gx, gy, bx, by); }
+ INLINE_AUTO_MAPPABLE(Chromaticities)
+
+ // -
+
+ static constexpr auto Rec709() { // AKA limited/studio/tv
+ return Chromaticities();
+ }
+ static constexpr auto Srgb() { return Rec709(); }
+
+ static constexpr auto Rec601_625_Pal() {
+ auto ret = Rec709();
+ ret.gx = 0.290;
+ return ret;
+ }
+ static constexpr auto Rec601_525_Ntsc() {
+ return Chromaticities{
+ 0.630, 0.340, // r
+ 0.310, 0.595, // g
+ 0.155, 0.070, // b
+ };
+ }
+ static constexpr auto Rec2020() {
+ return Chromaticities{
+ 0.708, 0.292, // r
+ 0.170, 0.797, // g
+ 0.131, 0.046, // b
+ };
+ }
+ static constexpr auto DisplayP3() {
+ return Chromaticities{
+ 0.680, 0.320, // r
+ 0.265, 0.690, // g
+ 0.150, 0.060, // b
+ };
+ }
+};
+
+// -
+
+struct YuvDesc final {
+ YuvLumaCoeffs yCoeffs;
+ YcbcrDesc ycbcr;
+
+ auto Members() const { return std::tie(yCoeffs, ycbcr); }
+ INLINE_AUTO_MAPPABLE(YuvDesc);
+};
+
+struct ColorspaceDesc final {
+ Chromaticities chrom;
+ std::optional<PiecewiseGammaDesc> tf;
+ std::optional<YuvDesc> yuv;
+
+ auto Members() const { return std::tie(chrom, tf, yuv); }
+ INLINE_AUTO_MAPPABLE(ColorspaceDesc);
+};
+
+// -
+
+template <class TT, int NN>
+struct avec final {
+ using T = TT;
+ static constexpr auto N = NN;
+
+ std::array<T, N> data = {};
+
+ // -
+
+ constexpr avec() = default;
+ constexpr avec(const avec&) = default;
+
+ constexpr avec(const avec<T, N - 1>& v, T a) {
+ for (int i = 0; i < N - 1; i++) {
+ data[i] = v[i];
+ }
+ data[N - 1] = a;
+ }
+ constexpr avec(const avec<T, N - 2>& v, T a, T b) {
+ for (int i = 0; i < N - 2; i++) {
+ data[i] = v[i];
+ }
+ data[N - 2] = a;
+ data[N - 1] = b;
+ }
+
+ MOZ_IMPLICIT constexpr avec(const std::array<T, N>& data) {
+ this->data = data;
+ }
+
+ explicit constexpr avec(const T v) {
+ for (int i = 0; i < N; i++) {
+ data[i] = v;
+ }
+ }
+
+ template <class T2, int N2>
+ explicit constexpr avec(const avec<T2, N2>& v) {
+ const auto n = std::min(N, N2);
+ for (int i = 0; i < n; i++) {
+ data[i] = static_cast<T>(v[i]);
+ }
+ }
+
+ // -
+
+ const auto& operator[](const size_t n) const { return data[n]; }
+ auto& operator[](const size_t n) { return data[n]; }
+
+ template <int i>
+ constexpr auto get() const {
+ return (i < N) ? data[i] : 0;
+ }
+ constexpr auto x() const { return get<0>(); }
+ constexpr auto y() const { return get<1>(); }
+ constexpr auto z() const { return get<2>(); }
+ constexpr auto w() const { return get<3>(); }
+
+ constexpr auto xyz() const { return vec3({x(), y(), z()}); }
+
+ template <int i>
+ void set(const T v) {
+ if (i < N) {
+ data[i] = v;
+ }
+ }
+ void x(const T v) { set<0>(v); }
+ void y(const T v) { set<1>(v); }
+ void z(const T v) { set<2>(v); }
+ void w(const T v) { set<3>(v); }
+
+ // -
+
+#define _(OP) \
+ friend avec operator OP(const avec a, const avec b) { \
+ avec c; \
+ for (int i = 0; i < N; i++) { \
+ c[i] = a[i] OP b[i]; \
+ } \
+ return c; \
+ } \
+ friend avec operator OP(const avec a, const T b) { \
+ avec c; \
+ for (int i = 0; i < N; i++) { \
+ c[i] = a[i] OP b; \
+ } \
+ return c; \
+ } \
+ friend avec operator OP(const T a, const avec b) { \
+ avec c; \
+ for (int i = 0; i < N; i++) { \
+ c[i] = a OP b[i]; \
+ } \
+ return c; \
+ }
+ _(+)
+ _(-)
+ _(*)
+ _(/)
+#undef _
+
+ friend bool operator==(const avec a, const avec b) {
+ bool eq = true;
+ for (int i = 0; i < N; i++) {
+ eq &= (a[i] == b[i]);
+ }
+ return eq;
+ }
+};
+using vec2 = avec<float, 2>;
+using vec3 = avec<float, 3>;
+using vec4 = avec<float, 4>;
+using ivec3 = avec<int32_t, 3>;
+using ivec4 = avec<int32_t, 4>;
+
+template <class T, int N>
+T dot(const avec<T, N>& a, const avec<T, N>& b) {
+ const auto c = a * b;
+ T ret = 0;
+ for (int i = 0; i < N; i++) {
+ ret += c[i];
+ }
+ return ret;
+}
+
+template <class V>
+V mix(const V& zero, const V& one, const float val) {
+ return zero * (1 - val) + one * val;
+}
+
+template <class T, int N>
+auto min(const avec<T, N>& a, const avec<T, N>& b) {
+ auto ret = avec<T, N>{};
+ for (int i = 0; i < ret.N; i++) {
+ ret[i] = std::min(a[i], b[i]);
+ }
+ return ret;
+}
+
+template <class T, int N>
+auto max(const avec<T, N>& a, const avec<T, N>& b) {
+ auto ret = avec<T, N>{};
+ for (int i = 0; i < ret.N; i++) {
+ ret[i] = std::max(a[i], b[i]);
+ }
+ return ret;
+}
+
+template <class T, int N>
+auto floor(const avec<T, N>& a) {
+ auto ret = avec<T, N>{};
+ for (int i = 0; i < ret.N; i++) {
+ ret[i] = floorf(a[i]);
+ }
+ return ret;
+}
+
+template <class T, int N>
+auto round(const avec<T, N>& a) {
+ auto ret = avec<T, N>{};
+ for (int i = 0; i < ret.N; i++) {
+ ret[i] = roundf(a[i]);
+ }
+ return ret;
+}
+
+template <class T, int N>
+auto abs(const avec<T, N>& a) {
+ auto ret = avec<T, N>{};
+ for (int i = 0; i < ret.N; i++) {
+ ret[i] = std::abs(a[i]);
+ }
+ return ret;
+}
+
+// -
+
+template <int Y_Rows, int X_Cols>
+struct mat final {
+ static constexpr int y_rows = Y_Rows;
+ static constexpr int x_cols = X_Cols;
+
+ static constexpr auto Identity() {
+ auto ret = mat{};
+ for (int i = 0; i < std::min(x_cols, y_rows); i++) {
+ ret.at(i, i) = 1;
+ }
+ return ret;
+ }
+ static constexpr auto Scale(const avec<float, std::min(x_cols, y_rows)>& v) {
+ auto ret = mat{};
+ for (int i = 0; i < v.N; i++) {
+ ret.at(i, i) = v[i];
+ }
+ return ret;
+ }
+
+ std::array<avec<float, X_Cols>, Y_Rows> rows = {}; // row-major
+
+ // -
+
+ constexpr mat() = default;
+
+ explicit constexpr mat(const std::array<avec<float, X_Cols>, Y_Rows>& rows) {
+ this->rows = rows;
+ }
+
+ template <int Y_Rows2, int X_Cols2>
+ explicit constexpr mat(const mat<Y_Rows2, X_Cols2>& m) {
+ *this = Identity();
+ for (int x = 0; x < std::min(X_Cols, X_Cols2); x++) {
+ for (int y = 0; y < std::min(Y_Rows, Y_Rows2); y++) {
+ at(x, y) = m.at(x, y);
+ }
+ }
+ }
+
+ const auto& at(const int x, const int y) const { return rows.at(y)[x]; }
+ auto& at(const int x, const int y) { return rows.at(y)[x]; }
+
+ friend auto operator*(const mat& a, const avec<float, X_Cols>& b_colvec) {
+ avec<float, Y_Rows> c_colvec;
+ for (int i = 0; i < y_rows; i++) {
+ c_colvec[i] = dot(a.rows.at(i), b_colvec);
+ }
+ return c_colvec;
+ }
+
+ friend auto operator*(const mat& a, const float b) {
+ mat c;
+ for (int x = 0; x < x_cols; x++) {
+ for (int y = 0; y < y_rows; y++) {
+ c.at(x, y) = a.at(x, y) * b;
+ }
+ }
+ return c;
+ }
+ friend auto operator/(const mat& a, const float b) { return a * (1 / b); }
+
+ template <int BCols, int BRows = X_Cols>
+ friend auto operator*(const mat& a, const mat<BRows, BCols>& b) {
+ const auto bt = transpose(b);
+ const auto& b_cols = bt.rows;
+
+ mat<Y_Rows, BCols> c;
+ for (int x = 0; x < BCols; x++) {
+ for (int y = 0; y < Y_Rows; y++) {
+ c.at(x, y) = dot(a.rows.at(y), b_cols.at(x));
+ }
+ }
+ return c;
+ }
+
+ // For e.g. similarity evaluation
+ friend auto operator-(const mat& a, const mat& b) {
+ mat c;
+ for (int y = 0; y < y_rows; y++) {
+ c.rows[y] = a.rows[y] - b.rows[y];
+ }
+ return c;
+ }
+};
+
+template <class M>
+inline float dotDifference(const M& a, const M& b) {
+ const auto c = a - b;
+ const auto d = c * avec<float, M::x_cols>(1);
+ const auto d2 = dot(d, d);
+ return d2;
+}
+template <class M>
+inline bool approx(const M& a, const M& b, const float eps = 0.0001) {
+ const auto errSquared = dotDifference(a, b);
+ return errSquared <= (eps * eps);
+}
+
+using mat3 = mat<3, 3>;
+using mat4 = mat<4, 4>;
+
+inline float determinant(const mat<1, 1>& m) { return m.at(0, 0); }
+template <class T>
+float determinant(const T& m) {
+ static_assert(T::x_cols == T::y_rows);
+
+ float ret = 0;
+ for (int i = 0; i < T::x_cols; i++) {
+ const auto cofact = cofactor(m, i, 0);
+ ret += m.at(i, 0) * cofact;
+ }
+ return ret;
+}
+
+// -
+
+template <class T>
+float cofactor(const T& m, const int x_col, const int y_row) {
+ ASSERT(0 <= x_col && x_col < T::x_cols);
+ ASSERT(0 <= y_row && y_row < T::y_rows);
+
+ auto cofactor = minor_val(m, x_col, y_row);
+ if ((x_col + y_row) % 2 == 1) {
+ cofactor *= -1;
+ }
+ return cofactor;
+}
+
+// -
+
+// Unfortunately, can't call this `minor(...)` because there is
+// `#define minor(dev) gnu_dev_minor (dev)`
+// in /usr/include/x86_64-linux-gnu/sys/sysmacros.h:62
+template <class T>
+float minor_val(const T& a, const int skip_x, const int skip_y) {
+ ASSERT(0 <= skip_x && skip_x < T::x_cols);
+ ASSERT(0 <= skip_y && skip_y < T::y_rows);
+
+ // A minor matrix is a matrix without its x_col and y_row.
+ mat<T::y_rows - 1, T::x_cols - 1> b;
+
+ int x_skips = 0;
+ for (int ax = 0; ax < T::x_cols; ax++) {
+ if (ax == skip_x) {
+ x_skips = 1;
+ continue;
+ }
+
+ int y_skips = 0;
+ for (int ay = 0; ay < T::y_rows; ay++) {
+ if (ay == skip_y) {
+ y_skips = 1;
+ continue;
+ }
+
+ b.at(ax - x_skips, ay - y_skips) = a.at(ax, ay);
+ }
+ }
+
+ const auto minor = determinant(b);
+ return minor;
+}
+
+// -
+
+/// The matrix of cofactors.
+template <class T>
+auto comatrix(const T& a) {
+ auto b = T{};
+ for (int x = 0; x < T::x_cols; x++) {
+ for (int y = 0; y < T::y_rows; y++) {
+ b.at(x, y) = cofactor(a, x, y);
+ }
+ }
+ return b;
+}
+
+// -
+
+template <class T>
+auto transpose(const T& a) {
+ auto b = mat<T::x_cols, T::y_rows>{};
+ for (int x = 0; x < T::x_cols; x++) {
+ for (int y = 0; y < T::y_rows; y++) {
+ b.at(y, x) = a.at(x, y);
+ }
+ }
+ return b;
+}
+
+// -
+
+template <class T>
+inline T inverse(const T& a) {
+ const auto det = determinant(a);
+ const auto comat = comatrix(a);
+ const auto adjugate = transpose(comat);
+ const auto inv = adjugate / det;
+ return inv;
+}
+
+// -
+
+template <class F>
+void ForEachIntWithin(const ivec3 size, const F& f) {
+ ivec3 p;
+ for (p.z(0); p.z() < size.z(); p.z(p.z() + 1)) {
+ for (p.y(0); p.y() < size.y(); p.y(p.y() + 1)) {
+ for (p.x(0); p.x() < size.x(); p.x(p.x() + 1)) {
+ f(p);
+ }
+ }
+ }
+}
+template <class F>
+void ForEachSampleWithin(const ivec3 size, const F& f) {
+ const auto div = vec3(size - 1);
+ ForEachIntWithin(size, [&](const ivec3& isrc) {
+ const auto fsrc = vec3(isrc) / div;
+ f(fsrc);
+ });
+}
+
+// -
+
+struct Lut3 final {
+ ivec3 size;
+ std::vector<vec3> data;
+
+ // -
+
+ static Lut3 Create(const ivec3 size) {
+ Lut3 lut;
+ lut.size = size;
+ lut.data.resize(size.x() * size.y() * size.z());
+ return lut;
+ }
+
+ // -
+
+ /// p: [0, N-1] (clamps)
+ size_t Index(ivec3 p) const {
+ const auto scales = ivec3({1, size.x(), size.x() * size.y()});
+ p = max(ivec3(0), min(p, size - 1)); // clamp
+ return dot(p, scales);
+ }
+
+ // -
+
+ template <class F>
+ void SetMap(const F& dstFromSrc01) {
+ ForEachIntWithin(size, [&](const ivec3 p) {
+ const auto i = Index(p);
+ const auto src01 = vec3(p) / vec3(size - 1);
+ const auto dstVal = dstFromSrc01(src01);
+ data.at(i) = dstVal;
+ });
+ }
+
+ // -
+
+ /// p: [0, N-1] (clamps)
+ vec3 Fetch(ivec3 p) const {
+ const auto i = Index(p);
+ return data.at(i);
+ }
+
+ /// in01: [0.0, 1.0] (clamps)
+ vec3 Sample(vec3 in01) const;
+};
+
+// -
+
+/**
+Naively, it would be ideal to map directly from ycbcr to rgb,
+but headroom and footroom are problematic: For e.g. narrow-range-8-bit,
+our naive LUT would start at absolute y=0/255. However, values only start
+at y=16/255, and depending on where your first LUT sample is, you might get
+very poor approximations for y=16/255.
+Further, even for full-range-8-bit, y=-0.5 is encoded as 1/255. U and v
+aren't *as* important as y, but we should try be accurate for the min and
+max values. Additionally, it would be embarassing to get whites/greys wrong,
+so preserving u=0.0 should also be a goal.
+Finally, when using non-linear transfer functions, the linear approximation of a
+point between two samples will be fairly inaccurate.
+We preserve min and max by choosing our input range such that min and max are
+the endpoints of their LUT axis.
+We preserve accuracy (at and around) mid by choosing odd sizes for dimentions.
+
+But also, the LUT is surprisingly robust, so check if the simple version works
+before adding complexity!
+**/
+
+struct ColorspaceTransform final {
+ ColorspaceDesc srcSpace;
+ ColorspaceDesc dstSpace;
+ mat4 srcRgbTfFromSrc;
+ std::optional<PiecewiseGammaDesc> srcTf;
+ mat3 dstRgbLinFromSrcRgbLin;
+ std::optional<PiecewiseGammaDesc> dstTf;
+ mat4 dstFromDstRgbTf;
+
+ static ColorspaceTransform Create(const ColorspaceDesc& src,
+ const ColorspaceDesc& dst);
+
+ // -
+
+ vec3 DstFromSrc(vec3 src) const;
+
+ std::optional<mat4> ToMat4() const;
+
+ Lut3 ToLut3(const ivec3 size) const;
+ Lut3 ToLut3() const {
+ auto defaultSize = ivec3({31, 31, 15}); // Order of importance: G, R, B
+ if (srcSpace.yuv) {
+ defaultSize = ivec3({31, 15, 31}); // Y, Cb, Cr
+ }
+ return ToLut3(defaultSize);
+ }
+};
+
+// -
+
+struct RgbTransferTables {
+ std::vector<float> r;
+ std::vector<float> g;
+ std::vector<float> b;
+};
+float GuessGamma(const std::vector<float>& vals, float exp_guess = 1.0);
+
+static constexpr auto D65 = vec2{{0.3127, 0.3290}};
+static constexpr auto D50 = vec2{{0.34567, 0.35850}};
+mat3 XyzAFromXyzB_BradfordLinear(const vec2 xyA, const vec2 xyB);
+
+// -
+
+struct ColorProfileDesc {
+ // ICC profiles are phrased as PCS-from-encoded (PCS is CIEXYZ-D50)
+ // However, all of our colorspaces are D65, so let's normalize to that,
+ // even though it's a reversible transform.
+ color::mat4 rgbFromYcbcr = color::mat4::Identity();
+ RgbTransferTables linearFromTf;
+ color::mat3 xyzd65FromLinearRgb = color::mat3::Identity();
+
+ static ColorProfileDesc From(const ColorspaceDesc&);
+ static ColorProfileDesc From(const qcms_profile&);
+};
+
+template <class C>
+inline float SampleOutByIn(const C& outByIn, const float in) {
+ switch (outByIn.size()) {
+ case 0:
+ return in;
+ case 1:
+ return outByIn.at(0);
+ }
+ MOZ_ASSERT(outByIn.size() >= 2);
+ const auto begin = outByIn.begin();
+
+ const auto in0i = size_t(floorf(in * (outByIn.size() - 1)));
+ const auto out0_itr = begin + std::min(in0i, outByIn.size() - 2);
+
+ const auto in0 = float(out0_itr - begin) / (outByIn.size() - 1);
+ const auto out0 = *out0_itr;
+ const auto d_in = float(1) / (outByIn.size() - 1);
+ const auto d_out = *(out0_itr + 1) - *out0_itr;
+
+ const auto out = out0 + (d_out / d_in) * (in - in0);
+ // printf("SampleOutByIn(%f)->%f\n", in, out);
+ return out;
+}
+
+template <class C>
+inline float SampleInByOut(const C& outByIn, const float out) {
+ MOZ_ASSERT(outByIn.size() >= 2);
+ const auto begin = outByIn.begin();
+
+ const auto out0_itr = std::lower_bound(begin + 1, outByIn.end() - 1, out) - 1;
+
+ const auto in0 = float(out0_itr - begin) / (outByIn.size() - 1);
+ const auto out0 = *out0_itr;
+ const auto d_in = float(1) / (outByIn.size() - 1);
+ const auto d_out = *(out0_itr + 1) - *out0_itr;
+
+ // printf("%f + (%f / %f) * (%f - %f)\n", in0, d_in, d_out, out, out0);
+ const auto in = in0 + (d_in / d_out) * (out - out0);
+ // printf("SampleInByOut(%f)->%f\n", out, in);
+ return in;
+}
+
+template <class C, class FnLessEqualT = std::less_equal<typename C::value_type>>
+inline bool IsMonotonic(const C& vals, const FnLessEqualT& LessEqual = {}) {
+ bool ok = true;
+ const auto begin = vals.begin();
+ for (size_t i = 1; i < vals.size(); i++) {
+ const auto itr = begin + i;
+ ok &= LessEqual(*(itr - 1), *itr);
+ // Assert(true, [&]() {
+ // return prints("[%zu]->%f <= [%zu]->%f", i-1, *(itr-1), i, *itr);
+ // });
+ }
+ return ok;
+}
+
+template <class T, class I>
+inline std::optional<I> SeekNeq(const T& ref, const I first, const I last) {
+ const auto inc = (last - first) > 0 ? 1 : -1;
+ auto itr = first;
+ while (true) {
+ if (*itr != ref) return itr;
+ if (itr == last) return {};
+ itr += inc;
+ }
+}
+
+template <class T>
+struct TwoPoints {
+ struct {
+ T x;
+ T y;
+ } p0;
+ struct {
+ T x;
+ T y;
+ } p1;
+
+ T y(const T x) const {
+ const auto dx = p1.x - p0.x;
+ const auto dy = p1.y - p0.y;
+ return p0.y + dy / dx * (x - p0.x);
+ }
+};
+
+/// Fills `vals` with `x:[0..vals.size()-1] => line.y(x)`.
+template <class T>
+static void LinearFill(T& vals, const TwoPoints<float>& line) {
+ float x = -1;
+ for (auto& val : vals) {
+ x += 1;
+ val = line.y(x);
+ }
+}
+
+// -
+
+inline void DequantizeMonotonic(const Span<float> vals) {
+ MOZ_ASSERT(IsMonotonic(vals));
+
+ const auto first = vals.begin();
+ const auto end = vals.end();
+ if (first == end) return;
+ const auto last = end - 1;
+ if (first == last) return;
+
+ // Three monotonic cases:
+ // 1. [0,0,0,0]
+ // 2. [0,0,1,1]
+ // 3. [0,1,1,2]
+
+ const auto body_first = SeekNeq(*first, first, last);
+ if (!body_first) {
+ // E.g. [0,0,0,0]
+ return;
+ }
+
+ const auto body_last = SeekNeq(*last, last, *body_first);
+ if (!body_last) {
+ // E.g. [0,0,1,1]
+ // This isn't the most accurate, but close enough.
+ // print("#2: %s", to_str(vals).c_str());
+ LinearFill(vals, {
+ {0, *first},
+ {float(vals.size() - 1), *last},
+ });
+ // print(" -> %s\n", to_str(vals).c_str());
+ return;
+ }
+
+ // E.g. [0,1,1,2]
+ // ^^^ body
+ // => f(0.5)->0.5, f(2.5)->1.5
+ // => f(x) = f(x0) + (x-x0) * (f(x1) - f(x0)) / (x1-x0)
+ // => f(x) = f(x0) + (x-x0) * dfdx
+
+ const auto head_end = *body_first;
+ const auto head = vals.subspan(0, head_end - vals.begin());
+ const auto tail_begin = *body_last + 1;
+ const auto tail = vals.subspan(tail_begin - vals.begin());
+ // print("head tail: %s %s\n",
+ // to_str(head).c_str(),
+ // to_str(tail).c_str());
+
+ // const auto body = vals->subspan(head.size(), vals->size()-tail.size());
+ auto next_part_first = head_end;
+ while (next_part_first != tail_begin) {
+ const auto part_first = next_part_first;
+ // print("part_first: %f\n", *part_first);
+ next_part_first = *SeekNeq(*part_first, part_first, tail_begin);
+ // print("next_part_first: %f\n", *next_part_first);
+ const auto part =
+ Span<float>{part_first, size_t(next_part_first - part_first)};
+ // print("part: %s\n", to_str(part).c_str());
+ const auto prev_part_last = part_first - 1;
+ const auto part_last = next_part_first - 1;
+ const auto line = TwoPoints<float>{
+ {-0.5, (*prev_part_last + *part_first) / 2},
+ {part.size() - 0.5f, (*part_last + *next_part_first) / 2},
+ };
+ LinearFill(part, line);
+ }
+
+ static constexpr bool INFER_HEAD_TAIL_FROM_BODY_EDGE = false;
+ // Basically ignore contents of head and tail, and infer from edges of body.
+ // print("3: %s\n", to_str(vals).c_str());
+ if (!IsMonotonic(head, std::less<float>{})) {
+ if (!INFER_HEAD_TAIL_FROM_BODY_EDGE) {
+ LinearFill(head,
+ {
+ {0, *head.begin()},
+ {head.size() - 0.5f, (*(head.end() - 1) + *head_end) / 2},
+ });
+ } else {
+ LinearFill(head, {
+ {head.size() + 0.0f, *head_end},
+ {head.size() + 1.0f, *(head_end + 1)},
+ });
+ }
+ }
+ if (!IsMonotonic(tail, std::less<float>{})) {
+ if (!INFER_HEAD_TAIL_FROM_BODY_EDGE) {
+ LinearFill(tail, {
+ {-0.5, (*(tail_begin - 1) + *tail.begin()) / 2},
+ {tail.size() - 1.0f, *(tail.end() - 1)},
+ });
+ } else {
+ LinearFill(tail, {
+ {-2.0f, *(tail_begin - 2)},
+ {-1.0f, *(tail_begin - 1)},
+ });
+ }
+ }
+ // print("3: %s\n", to_str(vals).c_str());
+ MOZ_ASSERT(IsMonotonic(vals, std::less<float>{}));
+
+ // Rescale, because we tend to lose range.
+ static constexpr bool RESCALE = false;
+ if (RESCALE) {
+ const auto firstv = *first;
+ const auto lastv = *last;
+ for (auto& val : vals) {
+ val = (val - firstv) / (lastv - firstv);
+ }
+ }
+ // print("4: %s\n", to_str(vals).c_str());
+}
+
+template <class In, class Out>
+static void InvertLut(const In& lut, Out* const out_invertedLut) {
+ MOZ_ASSERT(IsMonotonic(lut));
+ auto plut = &lut;
+ auto vec = std::vector<float>{};
+ if (!IsMonotonic(lut, std::less<float>{})) {
+ // print("Not strictly monotonic...\n");
+ vec.assign(lut.begin(), lut.end());
+ DequantizeMonotonic(vec);
+ plut = &vec;
+ // print(" Now strictly monotonic: %i: %s\n",
+ // int(IsMonotonic(*plut, std::less<float>{})), to_str(*plut).c_str());
+ MOZ_ASSERT(IsMonotonic(*plut, std::less<float>{}));
+ }
+ MOZ_ASSERT(plut->size() >= 2);
+
+ auto& ret = *out_invertedLut;
+ for (size_t i_out = 0; i_out < ret.size(); i_out++) {
+ const auto f_out = i_out / float(ret.size() - 1);
+ const auto f_in = SampleInByOut(*plut, f_out);
+ ret[i_out] = f_in;
+ }
+
+ MOZ_ASSERT(IsMonotonic(ret));
+ MOZ_ASSERT(IsMonotonic(ret, std::less<float>{}));
+}
+
+// -
+
+struct ColorProfileConversionDesc {
+ // ICC profiles are phrased as PCS-from-encoded (PCS is CIEXYZ-D50)
+ color::mat4 srcRgbFromSrcYuv = color::mat4::Identity();
+ RgbTransferTables srcLinearFromSrcTf;
+ color::mat3 dstLinearFromSrcLinear = color::mat3::Identity();
+ RgbTransferTables dstTfFromDstLinear;
+
+ struct FromDesc {
+ ColorProfileDesc src;
+ ColorProfileDesc dst;
+ };
+ static ColorProfileConversionDesc From(const FromDesc&);
+
+ vec3 Apply(const vec3 src) const {
+ const auto srcRgb = vec3(srcRgbFromSrcYuv * vec4(src, 1));
+ const auto srcLinear = vec3{{
+ SampleOutByIn(srcLinearFromSrcTf.r, srcRgb.x()),
+ SampleOutByIn(srcLinearFromSrcTf.g, srcRgb.y()),
+ SampleOutByIn(srcLinearFromSrcTf.b, srcRgb.z()),
+ }};
+ const auto dstLinear = dstLinearFromSrcLinear * srcLinear;
+ const auto dstRgb = vec3{{
+ SampleOutByIn(dstTfFromDstLinear.r, dstLinear.x()),
+ SampleOutByIn(dstTfFromDstLinear.g, dstLinear.y()),
+ SampleOutByIn(dstTfFromDstLinear.b, dstLinear.z()),
+ }};
+ return dstRgb;
+ }
+};
+
+} // namespace mozilla::color
+
+#undef ASSERT
+
+#endif // MOZILLA_GFX_GL_COLORSPACES_H_
diff --git a/gfx/gl/ForceDiscreteGPUHelperCGL.h b/gfx/gl/ForceDiscreteGPUHelperCGL.h
new file mode 100644
index 0000000000..523d76def3
--- /dev/null
+++ b/gfx/gl/ForceDiscreteGPUHelperCGL.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ForceDiscreteGPUHelperCGL_h_
+#define ForceDiscreteGPUHelperCGL_h_
+
+#include <OpenGL/OpenGL.h>
+
+/** This RAII helper guarantees that we're on the discrete GPU during its
+ * lifetime.
+ *
+ * As long as any ForceDiscreteGPUHelperCGL object is alive, we're on the
+ * discrete GPU.
+ */
+class ForceDiscreteGPUHelperCGL {
+ CGLPixelFormatObj mPixelFormatObj;
+
+ public:
+ ForceDiscreteGPUHelperCGL() : mPixelFormatObj(nullptr) {
+ // the code in this function is taken from Chromium,
+ // src/ui/gfx/gl/gl_context_cgl.cc, r122013
+ // BSD-style license, (c) The Chromium Authors
+ CGLPixelFormatAttribute attribs[1];
+ attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
+ GLint num_pixel_formats = 0;
+ CGLChoosePixelFormat(attribs, &mPixelFormatObj, &num_pixel_formats);
+ }
+
+ ~ForceDiscreteGPUHelperCGL() { CGLReleasePixelFormat(mPixelFormatObj); }
+};
+
+#endif // ForceDiscreteGPUHelperCGL_h_
diff --git a/gfx/gl/GLBlitHelper.cpp b/gfx/gl/GLBlitHelper.cpp
new file mode 100644
index 0000000000..dd9fa00235
--- /dev/null
+++ b/gfx/gl/GLBlitHelper.cpp
@@ -0,0 +1,1684 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLBlitHelper.h"
+
+#include "gfxEnv.h"
+#include "gfxUtils.h"
+#include "GLContext.h"
+#include "GLScreenBuffer.h"
+#include "GPUVideoImage.h"
+#include "HeapCopyOfStackArray.h"
+#include "ImageContainer.h"
+#include "ScopedGLHelpers.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Casting.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/gfx/Matrix.h"
+#include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/layers/LayersSurfaces.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "AndroidSurfaceTexture.h"
+# include "GLImages.h"
+# include "GLLibraryEGL.h"
+#endif
+
+#ifdef XP_MACOSX
+# include "GLContextCGL.h"
+# include "MacIOSurfaceImage.h"
+#endif
+
+#ifdef XP_WIN
+# include "mozilla/layers/D3D11ShareHandleImage.h"
+# include "mozilla/layers/D3D11TextureIMFSampleImage.h"
+# include "mozilla/layers/D3D11YCbCrImage.h"
+#endif
+
+#ifdef MOZ_WIDGET_GTK
+# include "mozilla/layers/DMABUFSurfaceImage.h"
+# include "mozilla/widget/DMABufSurface.h"
+# include "mozilla/widget/DMABufLibWrapper.h"
+#endif
+
+using mozilla::layers::PlanarYCbCrData;
+using mozilla::layers::PlanarYCbCrImage;
+
+namespace mozilla {
+namespace gl {
+
+// --
+
+static const char kFragPreprocHeader[] = R"(
+ #ifdef GL_ES
+ #ifdef GL_FRAGMENT_PRECISION_HIGH
+ #define MAXP highp
+ #endif
+ #else
+ #define MAXP highp
+ #endif
+ #ifndef MAXP
+ #define MAXP mediump
+ #endif
+
+ #if __VERSION__ >= 130
+ #define VARYING in
+ #else
+ #define VARYING varying
+ #endif
+ #if __VERSION__ >= 120
+ #define MAT4X3 mat4x3
+ #else
+ #define MAT4X3 mat4
+ #endif
+)";
+
+// -
+
+const char* const kFragHeader_Tex2D = R"(
+ #define SAMPLER sampler2D
+ #if __VERSION__ >= 130
+ #define TEXTURE texture
+ #else
+ #define TEXTURE texture2D
+ #endif
+)";
+const char* const kFragHeader_Tex2DRect = R"(
+ #define SAMPLER sampler2DRect
+ #if __VERSION__ >= 130
+ #define TEXTURE texture
+ #else
+ #define TEXTURE texture2DRect
+ #endif
+)";
+const char* const kFragHeader_TexExt = R"(
+ #extension GL_OES_EGL_image_external : enable
+ #extension GL_OES_EGL_image_external_essl3 : enable
+ #if __VERSION__ >= 130
+ #define TEXTURE texture
+ #else
+ #define TEXTURE texture2D
+ #endif
+ #define SAMPLER samplerExternalOES
+)";
+
+// -
+
+static const char kFragDeclHeader[] = R"(
+ precision PRECISION float;
+ #if __VERSION__ >= 130
+ #define FRAG_COLOR oFragColor
+ out vec4 FRAG_COLOR;
+ #else
+ #define FRAG_COLOR gl_FragColor
+ #endif
+)";
+
+// -
+
+const char* const kFragSample_OnePlane = R"(
+ VARYING mediump vec2 vTexCoord0;
+ uniform PRECISION SAMPLER uTex0;
+
+ vec4 metaSample() {
+ vec4 src = TEXTURE(uTex0, vTexCoord0);
+ return src;
+ }
+)";
+// Ideally this would just change the color-matrix it uses, but this is
+// acceptable debt for now.
+// `extern` so that we don't get ifdef-dependent const-var-unused Werrors.
+extern const char* const kFragSample_OnePlane_YUV_via_GBR = R"(
+ VARYING mediump vec2 vTexCoord0;
+ uniform PRECISION SAMPLER uTex0;
+
+ vec4 metaSample() {
+ vec4 yuva = TEXTURE(uTex0, vTexCoord0).gbra;
+ return yuva;
+ }
+)";
+const char* const kFragSample_TwoPlane = R"(
+ VARYING mediump vec2 vTexCoord0;
+ VARYING mediump vec2 vTexCoord1;
+ uniform PRECISION SAMPLER uTex0;
+ uniform PRECISION SAMPLER uTex1;
+
+ vec4 metaSample() {
+ vec4 src = TEXTURE(uTex0, vTexCoord0); // Keep r and a.
+ src.gb = TEXTURE(uTex1, vTexCoord1).rg;
+ return src;
+ }
+)";
+const char* const kFragSample_ThreePlane = R"(
+ VARYING mediump vec2 vTexCoord0;
+ VARYING mediump vec2 vTexCoord1;
+ uniform PRECISION SAMPLER uTex0;
+ uniform PRECISION SAMPLER uTex1;
+ uniform PRECISION SAMPLER uTex2;
+
+ vec4 metaSample() {
+ vec4 src = TEXTURE(uTex0, vTexCoord0); // Keep r and a.
+ src.g = TEXTURE(uTex1, vTexCoord1).r;
+ src.b = TEXTURE(uTex2, vTexCoord1).r;
+ return src;
+ }
+)";
+
+// -
+
+const char* const kFragConvert_None = R"(
+ vec3 metaConvert(vec3 src) {
+ return src;
+ }
+)";
+const char* const kFragConvert_BGR = R"(
+ vec3 metaConvert(vec3 src) {
+ return src.bgr;
+ }
+)";
+const char* const kFragConvert_ColorMatrix = R"(
+ uniform mediump MAT4X3 uColorMatrix;
+
+ vec3 metaConvert(vec3 src) {
+ return (uColorMatrix * vec4(src, 1)).rgb;
+ }
+)";
+const char* const kFragConvert_ColorLut = R"(
+ uniform PRECISION sampler3D uColorLut;
+
+ vec3 metaConvert(vec3 src) {
+ // Half-texel filtering hazard!
+ // E.g. For texture size of 2,
+ // E.g. 0.5/2=0.25 is still sampling 100% of texel 0, 0% of texel 1.
+ // For the LUT, we need 0.5/2=0.25 to filter 25/75 texel 0 and 1.
+ // That is, we need to adjust our sampling point such that it's 0.25 of the
+ // way from texel 0's center to texel 1's center.
+ // We need, for N=2:
+ // v=0.0|N=2 => v'=0.5/2
+ // v=1.0|N=2 => v'=1.5/2
+ // For N=3:
+ // v=0.0|N=3 => v'=0.5/3
+ // v=1.0|N=3 => v'=2.5/3
+ // => v' = ( 0.5 + v * (3 - 1) )/3
+ vec3 size = vec3(textureSize(uColorLut, 0));
+ src = (0.5 + src * (size - 1.0)) / size;
+ return texture(uColorLut, src).rgb;
+ }
+)";
+
+// -
+
+const char* const kFragMixin_AlphaMultColors = R"(
+ #define MIXIN_ALPHA_MULT_COLORS
+)";
+const char* const kFragMixin_AlphaClampColors = R"(
+ #define MIXIN_ALPHA_CLAMP_COLORS
+)";
+const char* const kFragMixin_AlphaOne = R"(
+ #define MIXIN_ALPHA_ONE
+)";
+
+// -
+
+static const char kFragBody[] = R"(
+ void main(void) {
+ vec4 src = metaSample();
+ vec4 dst = vec4(metaConvert(src.rgb), src.a);
+
+ #ifdef MIXIN_ALPHA_MULT_COLORS
+ dst.rgb *= dst.a;
+ #endif
+ #ifdef MIXIN_ALPHA_CLAMP_COLORS
+ dst.rgb = min(dst.rgb, vec3(dst.a)); // Ensure valid premult-alpha colors.
+ #endif
+ #ifdef MIXIN_ALPHA_ONE
+ dst.a = 1.0;
+ #endif
+
+ FRAG_COLOR = dst;
+ }
+)";
+
+// --
+
+Mat3 SubRectMat3(const float x, const float y, const float w, const float h) {
+ auto ret = Mat3{};
+ ret.at(0, 0) = w;
+ ret.at(1, 1) = h;
+ ret.at(2, 0) = x;
+ ret.at(2, 1) = y;
+ ret.at(2, 2) = 1.0f;
+ return ret;
+}
+
+Mat3 SubRectMat3(const gfx::IntRect& subrect, const gfx::IntSize& size) {
+ return SubRectMat3(float(subrect.X()) / size.width,
+ float(subrect.Y()) / size.height,
+ float(subrect.Width()) / size.width,
+ float(subrect.Height()) / size.height);
+}
+
+Mat3 SubRectMat3(const gfx::IntRect& bigSubrect, const gfx::IntSize& smallSize,
+ const gfx::IntSize& divisors) {
+ const float x = float(bigSubrect.X()) / divisors.width;
+ const float y = float(bigSubrect.Y()) / divisors.height;
+ const float w = float(bigSubrect.Width()) / divisors.width;
+ const float h = float(bigSubrect.Height()) / divisors.height;
+ return SubRectMat3(x / smallSize.width, y / smallSize.height,
+ w / smallSize.width, h / smallSize.height);
+}
+
+// --
+
+ScopedSaveMultiTex::ScopedSaveMultiTex(GLContext* const gl,
+ const std::vector<uint8_t>& texUnits,
+ const GLenum texTarget)
+ : mGL(*gl),
+ mTexUnits(texUnits),
+ mTexTarget(texTarget),
+ mOldTexUnit(mGL.GetIntAs<GLenum>(LOCAL_GL_ACTIVE_TEXTURE)) {
+ MOZ_RELEASE_ASSERT(texUnits.size() >= 1);
+
+ GLenum texBinding;
+ switch (mTexTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ texBinding = LOCAL_GL_TEXTURE_BINDING_2D;
+ break;
+ case LOCAL_GL_TEXTURE_3D:
+ texBinding = LOCAL_GL_TEXTURE_BINDING_3D;
+ break;
+ case LOCAL_GL_TEXTURE_RECTANGLE:
+ texBinding = LOCAL_GL_TEXTURE_BINDING_RECTANGLE;
+ break;
+ case LOCAL_GL_TEXTURE_EXTERNAL:
+ texBinding = LOCAL_GL_TEXTURE_BINDING_EXTERNAL;
+ break;
+ default:
+ gfxCriticalError() << "Unhandled texTarget: " << texTarget;
+ MOZ_CRASH();
+ }
+
+ for (const auto i : IntegerRange(mTexUnits.size())) {
+ const auto& unit = mTexUnits[i];
+ mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + unit);
+ if (mGL.IsSupported(GLFeature::sampler_objects)) {
+ mOldTexSampler[i] = mGL.GetIntAs<GLuint>(LOCAL_GL_SAMPLER_BINDING);
+ mGL.fBindSampler(unit, 0);
+ }
+ mOldTex[i] = mGL.GetIntAs<GLuint>(texBinding);
+ }
+}
+
+ScopedSaveMultiTex::~ScopedSaveMultiTex() {
+ // Unbind in reverse order, in case we have repeats.
+ // Order matters because we unbound samplers during ctor, so now we have to
+ // make sure we rebind them in the right order.
+ for (const auto i : Reversed(IntegerRange(mTexUnits.size()))) {
+ const auto& unit = mTexUnits[i];
+ mGL.fActiveTexture(LOCAL_GL_TEXTURE0 + unit);
+ if (mGL.IsSupported(GLFeature::sampler_objects)) {
+ mGL.fBindSampler(unit, mOldTexSampler[i]);
+ }
+ mGL.fBindTexture(mTexTarget, mOldTex[i]);
+ }
+ mGL.fActiveTexture(mOldTexUnit);
+}
+
+// --
+
+class ScopedBindArrayBuffer final {
+ public:
+ GLContext& mGL;
+ const GLuint mOldVBO;
+
+ ScopedBindArrayBuffer(GLContext* const gl, const GLuint vbo)
+ : mGL(*gl), mOldVBO(mGL.GetIntAs<GLuint>(LOCAL_GL_ARRAY_BUFFER_BINDING)) {
+ mGL.fBindBuffer(LOCAL_GL_ARRAY_BUFFER, vbo);
+ }
+
+ ~ScopedBindArrayBuffer() { mGL.fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mOldVBO); }
+};
+
+// --
+
+class ScopedShader final {
+ GLContext& mGL;
+ const GLuint mName;
+
+ public:
+ ScopedShader(GLContext* const gl, const GLenum shaderType)
+ : mGL(*gl), mName(mGL.fCreateShader(shaderType)) {}
+
+ ~ScopedShader() { mGL.fDeleteShader(mName); }
+
+ operator GLuint() const { return mName; }
+};
+
+// --
+
+class SaveRestoreCurrentProgram final {
+ GLContext& mGL;
+ const GLuint mOld;
+
+ public:
+ explicit SaveRestoreCurrentProgram(GLContext* const gl)
+ : mGL(*gl), mOld(mGL.GetIntAs<GLuint>(LOCAL_GL_CURRENT_PROGRAM)) {}
+
+ ~SaveRestoreCurrentProgram() { mGL.fUseProgram(mOld); }
+};
+
+// --
+
+class ScopedDrawBlitState final {
+ GLContext& mGL;
+
+ const bool blend;
+ const bool cullFace;
+ const bool depthTest;
+ const bool dither;
+ const bool polyOffsFill;
+ const bool sampleAToC;
+ const bool sampleCover;
+ const bool scissor;
+ const bool stencil;
+ Maybe<bool> rasterizerDiscard;
+
+ realGLboolean colorMask[4];
+ GLint viewport[4];
+
+ public:
+ ScopedDrawBlitState(GLContext* const gl, const gfx::IntSize& destSize)
+ : mGL(*gl),
+ blend(mGL.PushEnabled(LOCAL_GL_BLEND, false)),
+ cullFace(mGL.PushEnabled(LOCAL_GL_CULL_FACE, false)),
+ depthTest(mGL.PushEnabled(LOCAL_GL_DEPTH_TEST, false)),
+ dither(mGL.PushEnabled(LOCAL_GL_DITHER, true)),
+ polyOffsFill(mGL.PushEnabled(LOCAL_GL_POLYGON_OFFSET_FILL, false)),
+ sampleAToC(mGL.PushEnabled(LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false)),
+ sampleCover(mGL.PushEnabled(LOCAL_GL_SAMPLE_COVERAGE, false)),
+ scissor(mGL.PushEnabled(LOCAL_GL_SCISSOR_TEST, false)),
+ stencil(mGL.PushEnabled(LOCAL_GL_STENCIL_TEST, false)) {
+ if (mGL.IsSupported(GLFeature::transform_feedback2)) {
+ // Technically transform_feedback2 requires transform_feedback, which
+ // actually adds RASTERIZER_DISCARD.
+ rasterizerDiscard =
+ Some(mGL.PushEnabled(LOCAL_GL_RASTERIZER_DISCARD, false));
+ }
+
+ mGL.fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorMask);
+ if (mGL.IsSupported(GLFeature::draw_buffers_indexed)) {
+ mGL.fColorMaski(0, true, true, true, true);
+ } else {
+ mGL.fColorMask(true, true, true, true);
+ }
+
+ mGL.fGetIntegerv(LOCAL_GL_VIEWPORT, viewport);
+ MOZ_ASSERT(destSize.width && destSize.height);
+ mGL.fViewport(0, 0, destSize.width, destSize.height);
+ }
+
+ ~ScopedDrawBlitState() {
+ mGL.SetEnabled(LOCAL_GL_BLEND, blend);
+ mGL.SetEnabled(LOCAL_GL_CULL_FACE, cullFace);
+ mGL.SetEnabled(LOCAL_GL_DEPTH_TEST, depthTest);
+ mGL.SetEnabled(LOCAL_GL_DITHER, dither);
+ mGL.SetEnabled(LOCAL_GL_POLYGON_OFFSET_FILL, polyOffsFill);
+ mGL.SetEnabled(LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, sampleAToC);
+ mGL.SetEnabled(LOCAL_GL_SAMPLE_COVERAGE, sampleCover);
+ mGL.SetEnabled(LOCAL_GL_SCISSOR_TEST, scissor);
+ mGL.SetEnabled(LOCAL_GL_STENCIL_TEST, stencil);
+ if (rasterizerDiscard) {
+ mGL.SetEnabled(LOCAL_GL_RASTERIZER_DISCARD, rasterizerDiscard.value());
+ }
+
+ if (mGL.IsSupported(GLFeature::draw_buffers_indexed)) {
+ mGL.fColorMaski(0, colorMask[0], colorMask[1], colorMask[2],
+ colorMask[3]);
+ } else {
+ mGL.fColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
+ }
+ mGL.fViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
+ }
+};
+
+// --
+
+DrawBlitProg::DrawBlitProg(const GLBlitHelper* const parent, const GLuint prog)
+ : mParent(*parent),
+ mProg(prog),
+ mLoc_uDestMatrix(mParent.mGL->fGetUniformLocation(mProg, "uDestMatrix")),
+ mLoc_uTexMatrix0(mParent.mGL->fGetUniformLocation(mProg, "uTexMatrix0")),
+ mLoc_uTexMatrix1(mParent.mGL->fGetUniformLocation(mProg, "uTexMatrix1")),
+ mLoc_uColorLut(mParent.mGL->fGetUniformLocation(mProg, "uColorLut")),
+ mLoc_uColorMatrix(
+ mParent.mGL->fGetUniformLocation(mProg, "uColorMatrix")) {
+ const auto& gl = mParent.mGL;
+ MOZ_GL_ASSERT(gl, mLoc_uDestMatrix != -1); // Required
+ MOZ_GL_ASSERT(gl, mLoc_uTexMatrix0 != -1); // Required
+ if (mLoc_uColorMatrix != -1) {
+ MOZ_GL_ASSERT(gl, mLoc_uTexMatrix1 != -1);
+
+ int32_t numActiveUniforms = 0;
+ gl->fGetProgramiv(mProg, LOCAL_GL_ACTIVE_UNIFORMS, &numActiveUniforms);
+
+ const size_t kMaxNameSize = 32;
+ char name[kMaxNameSize] = {0};
+ GLint size = 0;
+ GLenum type = 0;
+ for (int32_t i = 0; i < numActiveUniforms; i++) {
+ gl->fGetActiveUniform(mProg, i, kMaxNameSize, nullptr, &size, &type,
+ name);
+ if (strcmp("uColorMatrix", name) == 0) {
+ mType_uColorMatrix = type;
+ break;
+ }
+ }
+ MOZ_GL_ASSERT(gl, mType_uColorMatrix);
+ }
+}
+
+DrawBlitProg::~DrawBlitProg() {
+ const auto& gl = mParent.mGL;
+ if (!gl->MakeCurrent()) return;
+
+ gl->fDeleteProgram(mProg);
+}
+
+void DrawBlitProg::Draw(const BaseArgs& args,
+ const YUVArgs* const argsYUV) const {
+ const auto& gl = mParent.mGL;
+
+ const SaveRestoreCurrentProgram oldProg(gl);
+ gl->fUseProgram(mProg);
+
+ // --
+
+ Mat3 destMatrix;
+ if (args.destRect) {
+ const auto& destRect = args.destRect.value();
+ destMatrix = SubRectMat3(destRect.X() / args.destSize.width,
+ destRect.Y() / args.destSize.height,
+ destRect.Width() / args.destSize.width,
+ destRect.Height() / args.destSize.height);
+ } else {
+ destMatrix = Mat3::I();
+ }
+
+ if (args.yFlip) {
+ // Apply the y-flip matrix before the destMatrix.
+ // That is, flip y=[0-1] to y=[1-0] before we restrict to the destRect.
+ destMatrix.at(2, 1) += destMatrix.at(1, 1);
+ destMatrix.at(1, 1) *= -1.0f;
+ }
+
+ gl->fUniformMatrix3fv(mLoc_uDestMatrix, 1, false, destMatrix.m);
+ gl->fUniformMatrix3fv(mLoc_uTexMatrix0, 1, false, args.texMatrix0.m);
+
+ if (args.texUnitForColorLut) {
+ gl->fUniform1i(mLoc_uColorLut,
+ AssertedCast<GLint>(*args.texUnitForColorLut));
+ }
+
+ MOZ_ASSERT(bool(argsYUV) == (mLoc_uColorMatrix != -1));
+ if (argsYUV) {
+ gl->fUniformMatrix3fv(mLoc_uTexMatrix1, 1, false, argsYUV->texMatrix1.m);
+
+ if (mLoc_uColorMatrix != -1) {
+ const auto& colorMatrix =
+ gfxUtils::YuvToRgbMatrix4x4ColumnMajor(*argsYUV->colorSpaceForMatrix);
+ float mat4x3[4 * 3];
+ switch (mType_uColorMatrix) {
+ case LOCAL_GL_FLOAT_MAT4:
+ gl->fUniformMatrix4fv(mLoc_uColorMatrix, 1, false, colorMatrix);
+ break;
+ case LOCAL_GL_FLOAT_MAT4x3:
+ for (int x = 0; x < 4; x++) {
+ for (int y = 0; y < 3; y++) {
+ mat4x3[3 * x + y] = colorMatrix[4 * x + y];
+ }
+ }
+ gl->fUniformMatrix4x3fv(mLoc_uColorMatrix, 1, false, mat4x3);
+ break;
+ default:
+ gfxCriticalError()
+ << "Bad mType_uColorMatrix: " << gfx::hexa(mType_uColorMatrix);
+ }
+ }
+ }
+
+ // --
+
+ const ScopedDrawBlitState drawState(gl, args.destSize);
+
+ GLuint oldVAO;
+ GLint vaa0Enabled;
+ GLint vaa0Size;
+ GLenum vaa0Type;
+ GLint vaa0Normalized;
+ GLsizei vaa0Stride;
+ GLvoid* vaa0Pointer;
+ GLuint vaa0Buffer;
+ if (mParent.mQuadVAO) {
+ oldVAO = gl->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
+ gl->fBindVertexArray(mParent.mQuadVAO);
+ } else {
+ // clang-format off
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, (GLint*)&vaa0Buffer);
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vaa0Enabled);
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &vaa0Size);
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, (GLint*)&vaa0Type);
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vaa0Normalized);
+ gl->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, (GLint*)&vaa0Stride);
+ gl->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &vaa0Pointer);
+ // clang-format on
+
+ gl->fEnableVertexAttribArray(0);
+ const ScopedBindArrayBuffer bindVBO(gl, mParent.mQuadVBO);
+ gl->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
+ }
+
+ gl->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
+
+ if (mParent.mQuadVAO) {
+ gl->fBindVertexArray(oldVAO);
+ } else {
+ if (vaa0Enabled) {
+ gl->fEnableVertexAttribArray(0);
+ } else {
+ gl->fDisableVertexAttribArray(0);
+ }
+ // The current VERTEX_ARRAY_BINDING is not necessarily the same as the
+ // buffer set for vaa0Buffer.
+ const ScopedBindArrayBuffer bindVBO(gl, vaa0Buffer);
+ gl->fVertexAttribPointer(0, vaa0Size, vaa0Type, bool(vaa0Normalized),
+ vaa0Stride, vaa0Pointer);
+ }
+}
+
+// --
+
+GLBlitHelper::GLBlitHelper(GLContext* const gl)
+ : mGL(gl),
+ mDrawBlitProg_VertShader(mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER))
+//, mYuvUploads_YSize(0, 0)
+//, mYuvUploads_UVSize(0, 0)
+{
+ mGL->fGenBuffers(1, &mQuadVBO);
+ {
+ const ScopedBindArrayBuffer bindVBO(mGL, mQuadVBO);
+
+ const float quadData[] = {0, 0, 1, 0, 0, 1, 1, 1};
+ const HeapCopyOfStackArray<float> heapQuadData(quadData);
+ mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, heapQuadData.ByteLength(),
+ heapQuadData.Data(), LOCAL_GL_STATIC_DRAW);
+
+ if (mGL->IsSupported(GLFeature::vertex_array_object)) {
+ const auto prev = mGL->GetIntAs<GLuint>(LOCAL_GL_VERTEX_ARRAY_BINDING);
+
+ mGL->fGenVertexArrays(1, &mQuadVAO);
+ mGL->fBindVertexArray(mQuadVAO);
+ mGL->fEnableVertexAttribArray(0);
+ mGL->fVertexAttribPointer(0, 2, LOCAL_GL_FLOAT, false, 0, 0);
+
+ mGL->fBindVertexArray(prev);
+ }
+ }
+
+ // --
+
+ const auto glslVersion = mGL->ShadingLanguageVersion();
+
+ if (mGL->IsGLES()) {
+ // If you run into problems on old android devices, it might be because some
+ // devices have OES_EGL_image_external but not OES_EGL_image_external_essl3.
+ // We could just use 100 in that particular case, but then we lose out on
+ // e.g. sampler3D. Let's just try 300 for now, and if we get regressions
+ // we'll add an essl100 fallback.
+ if (glslVersion >= 300) {
+ mDrawBlitProg_VersionLine = nsCString("#version 300 es\n");
+ } else {
+ mDrawBlitProg_VersionLine = nsCString("#version 100\n");
+ }
+ } else if (glslVersion >= 130) {
+ mDrawBlitProg_VersionLine = nsPrintfCString("#version %u\n", glslVersion);
+ }
+
+ const char kVertSource[] =
+ "\
+ #if __VERSION__ >= 130 \n\
+ #define ATTRIBUTE in \n\
+ #define VARYING out \n\
+ #else \n\
+ #define ATTRIBUTE attribute \n\
+ #define VARYING varying \n\
+ #endif \n\
+ \n\
+ ATTRIBUTE vec2 aVert; // [0.0-1.0] \n\
+ \n\
+ uniform mat3 uDestMatrix; \n\
+ uniform mat3 uTexMatrix0; \n\
+ uniform mat3 uTexMatrix1; \n\
+ \n\
+ VARYING vec2 vTexCoord0; \n\
+ VARYING vec2 vTexCoord1; \n\
+ \n\
+ void main(void) \n\
+ { \n\
+ vec2 destPos = (uDestMatrix * vec3(aVert, 1.0)).xy; \n\
+ gl_Position = vec4(destPos * 2.0 - 1.0, 0.0, 1.0); \n\
+ \n\
+ vTexCoord0 = (uTexMatrix0 * vec3(aVert, 1.0)).xy; \n\
+ vTexCoord1 = (uTexMatrix1 * vec3(aVert, 1.0)).xy; \n\
+ } \n\
+ ";
+ const char* const parts[] = {mDrawBlitProg_VersionLine.get(), kVertSource};
+ mGL->fShaderSource(mDrawBlitProg_VertShader, ArrayLength(parts), parts,
+ nullptr);
+ mGL->fCompileShader(mDrawBlitProg_VertShader);
+}
+
+GLBlitHelper::~GLBlitHelper() {
+ for (const auto& pair : mDrawBlitProgs) {
+ const auto& ptr = pair.second;
+ delete ptr;
+ }
+ mDrawBlitProgs.clear();
+
+ if (!mGL->MakeCurrent()) return;
+
+ mGL->fDeleteShader(mDrawBlitProg_VertShader);
+ mGL->fDeleteBuffers(1, &mQuadVBO);
+
+ if (mQuadVAO) {
+ mGL->fDeleteVertexArrays(1, &mQuadVAO);
+ }
+}
+
+// --
+
+const DrawBlitProg* GLBlitHelper::GetDrawBlitProg(
+ const DrawBlitProg::Key& key) const {
+ const auto& res = mDrawBlitProgs.insert({key, nullptr});
+ auto& pair = *(res.first);
+ const auto& didInsert = res.second;
+ if (didInsert) {
+ pair.second = CreateDrawBlitProg(pair.first);
+ }
+ return pair.second;
+}
+
+const DrawBlitProg* GLBlitHelper::CreateDrawBlitProg(
+ const DrawBlitProg::Key& key) const {
+ const auto precisionPref = StaticPrefs::gfx_blithelper_precision();
+ const char* precision;
+ switch (precisionPref) {
+ case 0:
+ precision = "lowp";
+ break;
+ case 1:
+ precision = "mediump";
+ break;
+ default:
+ if (precisionPref != 2) {
+ NS_WARNING("gfx.blithelper.precision clamped to 2.");
+ }
+ precision = "MAXP";
+ break;
+ }
+
+ nsPrintfCString precisionLine("\n#define PRECISION %s\n", precision);
+
+ // -
+
+ const ScopedShader fs(mGL, LOCAL_GL_FRAGMENT_SHADER);
+
+ std::vector<const char*> parts;
+ {
+ parts.push_back(mDrawBlitProg_VersionLine.get());
+ parts.push_back(kFragPreprocHeader);
+ if (key.fragHeader) {
+ parts.push_back(key.fragHeader);
+ }
+ parts.push_back(precisionLine.BeginReading());
+ parts.push_back(kFragDeclHeader);
+ for (const auto& part : key.fragParts) {
+ if (part) {
+ parts.push_back(part);
+ }
+ }
+ parts.push_back(kFragBody);
+ }
+
+ const auto PrintFragSource = [&]() {
+ printf_stderr("Frag source:\n");
+ int i = 0;
+ for (const auto& part : parts) {
+ printf_stderr("// parts[%i]:\n%s\n", i, part);
+ i += 1;
+ }
+ };
+ if (gfxEnv::MOZ_DUMP_GLBLITHELPER()) {
+ PrintFragSource();
+ }
+
+ mGL->fShaderSource(fs, AssertedCast<GLint>(parts.size()), parts.data(),
+ nullptr);
+ mGL->fCompileShader(fs);
+
+ const auto prog = mGL->fCreateProgram();
+ mGL->fAttachShader(prog, mDrawBlitProg_VertShader);
+ mGL->fAttachShader(prog, fs);
+
+ mGL->fBindAttribLocation(prog, 0, "aVert");
+ mGL->fLinkProgram(prog);
+
+ GLenum status = 0;
+ mGL->fGetProgramiv(prog, LOCAL_GL_LINK_STATUS, (GLint*)&status);
+ if (status == LOCAL_GL_TRUE || mGL->CheckContextLost()) {
+ const SaveRestoreCurrentProgram oldProg(mGL);
+ mGL->fUseProgram(prog);
+ const char* samplerNames[] = {"uTex0", "uTex1", "uTex2"};
+ for (int i = 0; i < 3; i++) {
+ const auto loc = mGL->fGetUniformLocation(prog, samplerNames[i]);
+ if (loc == -1) continue;
+ mGL->fUniform1i(loc, i);
+ }
+
+ return new DrawBlitProg(this, prog);
+ }
+
+ GLuint progLogLen = 0;
+ mGL->fGetProgramiv(prog, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&progLogLen);
+ const UniquePtr<char[]> progLog(new char[progLogLen + 1]);
+ mGL->fGetProgramInfoLog(prog, progLogLen, nullptr, progLog.get());
+ progLog[progLogLen] = 0;
+
+ const auto& vs = mDrawBlitProg_VertShader;
+ GLuint vsLogLen = 0;
+ mGL->fGetShaderiv(vs, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&vsLogLen);
+ const UniquePtr<char[]> vsLog(new char[vsLogLen + 1]);
+ mGL->fGetShaderInfoLog(vs, vsLogLen, nullptr, vsLog.get());
+ vsLog[vsLogLen] = 0;
+
+ GLuint fsLogLen = 0;
+ mGL->fGetShaderiv(fs, LOCAL_GL_INFO_LOG_LENGTH, (GLint*)&fsLogLen);
+ const UniquePtr<char[]> fsLog(new char[fsLogLen + 1]);
+ mGL->fGetShaderInfoLog(fs, fsLogLen, nullptr, fsLog.get());
+ fsLog[fsLogLen] = 0;
+
+ const auto logs =
+ std::string("DrawBlitProg link failed:\n") + "progLog: " + progLog.get() +
+ "\n" + "vsLog: " + vsLog.get() + "\n" + "fsLog: " + fsLog.get() + "\n";
+ gfxCriticalError() << logs;
+
+ PrintFragSource();
+
+ MOZ_CRASH("DrawBlitProg link failed");
+}
+
+// -----------------------------------------------------------------------------
+
+#ifdef XP_MACOSX
+static RefPtr<MacIOSurface> LookupSurface(
+ const layers::SurfaceDescriptorMacIOSurface& sd) {
+ return MacIOSurface::LookupSurface(sd.surfaceId(), !sd.isOpaque(),
+ sd.yUVColorSpace());
+}
+#endif
+
+bool GLBlitHelper::BlitSdToFramebuffer(const layers::SurfaceDescriptor& asd,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) {
+ const auto sdType = asd.type();
+ switch (sdType) {
+ case layers::SurfaceDescriptor::TSurfaceDescriptorBuffer: {
+ const auto& sd = asd.get_SurfaceDescriptorBuffer();
+ const auto yuvData = PlanarYCbCrData::From(sd);
+ if (!yuvData) {
+ gfxCriticalNote << "[GLBlitHelper::BlitSdToFramebuffer] "
+ "PlanarYCbCrData::From failed";
+ return false;
+ }
+ return BlitPlanarYCbCr(*yuvData, destSize, destOrigin);
+ }
+#ifdef XP_WIN
+ case layers::SurfaceDescriptor::TSurfaceDescriptorD3D10: {
+ const auto& sd = asd.get_SurfaceDescriptorD3D10();
+ return BlitDescriptor(sd, destSize, destOrigin);
+ }
+ case layers::SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
+ const auto& sd = asd.get_SurfaceDescriptorDXGIYCbCr();
+ return BlitDescriptor(sd, destSize, destOrigin);
+ }
+#endif
+#ifdef XP_MACOSX
+ case layers::SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
+ const auto& sd = asd.get_SurfaceDescriptorMacIOSurface();
+ const auto surf = LookupSurface(sd);
+ if (!surf) {
+ NS_WARNING("LookupSurface(MacIOSurface) failed");
+ // Sometimes that frame for our handle gone already. That's life, for
+ // now.
+ return false;
+ }
+ return BlitImage(surf, destSize, destOrigin);
+ }
+#endif
+#ifdef MOZ_WIDGET_ANDROID
+ case layers::SurfaceDescriptor::TSurfaceTextureDescriptor: {
+ const auto& sd = asd.get_SurfaceTextureDescriptor();
+ auto surfaceTexture = java::GeckoSurfaceTexture::Lookup(sd.handle());
+ return Blit(surfaceTexture, destSize, destOrigin);
+ }
+#endif
+#ifdef MOZ_WIDGET_GTK
+ case layers::SurfaceDescriptor::TSurfaceDescriptorDMABuf: {
+ const auto& sd = asd.get_SurfaceDescriptorDMABuf();
+ RefPtr<DMABufSurface> surface = DMABufSurface::CreateDMABufSurface(sd);
+ return Blit(surface, destSize, destOrigin);
+ }
+#endif
+ default:
+ return false;
+ }
+}
+
+bool GLBlitHelper::BlitImageToFramebuffer(layers::Image* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) {
+ switch (srcImage->GetFormat()) {
+ case ImageFormat::PLANAR_YCBCR: {
+ const auto srcImage2 = static_cast<PlanarYCbCrImage*>(srcImage);
+ const auto data = srcImage2->GetData();
+ return BlitPlanarYCbCr(*data, destSize, destOrigin);
+ }
+
+ case ImageFormat::SURFACE_TEXTURE: {
+#ifdef MOZ_WIDGET_ANDROID
+ auto* image = srcImage->AsSurfaceTextureImage();
+ MOZ_ASSERT(image);
+ auto surfaceTexture =
+ java::GeckoSurfaceTexture::Lookup(image->GetHandle());
+ return Blit(surfaceTexture, destSize, destOrigin);
+#else
+ MOZ_ASSERT(false);
+ return false;
+#endif
+ }
+ case ImageFormat::MAC_IOSURFACE:
+#ifdef XP_MACOSX
+ return BlitImage(srcImage->AsMacIOSurfaceImage(), destSize, destOrigin);
+#else
+ MOZ_ASSERT(false);
+ return false;
+#endif
+
+ case ImageFormat::GPU_VIDEO:
+ return BlitImage(static_cast<layers::GPUVideoImage*>(srcImage), destSize,
+ destOrigin);
+#ifdef XP_WIN
+ case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE:
+ return BlitImage(static_cast<layers::D3D11ShareHandleImage*>(srcImage),
+ destSize, destOrigin);
+ case ImageFormat::D3D11_TEXTURE_IMF_SAMPLE:
+ return BlitImage(
+ static_cast<layers::D3D11TextureIMFSampleImage*>(srcImage), destSize,
+ destOrigin);
+ case ImageFormat::D3D11_YCBCR_IMAGE:
+ return BlitImage(static_cast<layers::D3D11YCbCrImage*>(srcImage),
+ destSize, destOrigin);
+ case ImageFormat::D3D9_RGB32_TEXTURE:
+ return false; // todo
+ case ImageFormat::DCOMP_SURFACE:
+ return false;
+#else
+ case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE:
+ case ImageFormat::D3D11_TEXTURE_IMF_SAMPLE:
+ case ImageFormat::D3D11_YCBCR_IMAGE:
+ case ImageFormat::D3D9_RGB32_TEXTURE:
+ case ImageFormat::DCOMP_SURFACE:
+ MOZ_ASSERT(false);
+ return false;
+#endif
+ case ImageFormat::DMABUF:
+#ifdef MOZ_WIDGET_GTK
+ return BlitImage(static_cast<layers::DMABUFSurfaceImage*>(srcImage),
+ destSize, destOrigin);
+#else
+ return false;
+#endif
+ case ImageFormat::MOZ2D_SURFACE:
+ case ImageFormat::NV_IMAGE:
+ case ImageFormat::OVERLAY_IMAGE:
+ case ImageFormat::SHARED_RGB:
+ case ImageFormat::TEXTURE_WRAPPER:
+ return false; // todo
+ }
+ return false;
+}
+
+// -------------------------------------
+
+#ifdef MOZ_WIDGET_ANDROID
+bool GLBlitHelper::Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ if (!surfaceTexture) {
+ return false;
+ }
+
+ const ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0);
+
+ if (!surfaceTexture->IsAttachedToGLContext((int64_t)mGL)) {
+ GLuint tex;
+ mGL->MakeCurrent();
+ mGL->fGenTextures(1, &tex);
+
+ if (NS_FAILED(surfaceTexture->AttachToGLContext((int64_t)mGL, tex))) {
+ mGL->fDeleteTextures(1, &tex);
+ return false;
+ }
+ }
+
+ const ScopedBindTexture savedTex(mGL, surfaceTexture->GetTexName(),
+ LOCAL_GL_TEXTURE_EXTERNAL);
+ surfaceTexture->UpdateTexImage();
+ const auto transform3 = Mat3::I();
+ // const auto srcOrigin = OriginPos::TopLeft;
+ const auto srcOrigin = OriginPos::BottomLeft;
+ const bool yFlip = (srcOrigin != destOrigin);
+ const auto& prog = GetDrawBlitProg(
+ {kFragHeader_TexExt, {kFragSample_OnePlane, kFragConvert_None}});
+ const DrawBlitProg::BaseArgs baseArgs = {transform3, yFlip, destSize,
+ Nothing()};
+ prog->Draw(baseArgs, nullptr);
+
+ if (surfaceTexture->IsSingleBuffer()) {
+ surfaceTexture->ReleaseTexImage();
+ }
+
+ return true;
+}
+#endif
+
+// -------------------------------------
+
+bool GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
+ gfx::IntSize* const out_divisors) {
+ const gfx::IntSize divisors((ySize.width == uvSize.width) ? 1 : 2,
+ (ySize.height == uvSize.height) ? 1 : 2);
+ if (uvSize.width * divisors.width != ySize.width ||
+ uvSize.height * divisors.height != ySize.height) {
+ return false;
+ }
+ *out_divisors = divisors;
+ return true;
+}
+
+bool GLBlitHelper::BlitPlanarYCbCr(const PlanarYCbCrData& yuvData,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) {
+ const auto& prog = GetDrawBlitProg(
+ {kFragHeader_Tex2D, {kFragSample_ThreePlane, kFragConvert_ColorMatrix}});
+
+ if (!mYuvUploads[0]) {
+ mGL->fGenTextures(3, mYuvUploads);
+ const ScopedBindTexture bindTex(mGL, mYuvUploads[0]);
+ mGL->TexParams_SetClampNoMips();
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[1]);
+ mGL->TexParams_SetClampNoMips();
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[2]);
+ mGL->TexParams_SetClampNoMips();
+ }
+
+ // --
+
+ auto ySize = yuvData.YDataSize();
+ auto cbcrSize = yuvData.CbCrDataSize();
+ if (yuvData.mYSkip || yuvData.mCbSkip || yuvData.mCrSkip || ySize.width < 0 ||
+ ySize.height < 0 || cbcrSize.width < 0 || cbcrSize.height < 0 ||
+ yuvData.mYStride < 0 || yuvData.mCbCrStride < 0) {
+ gfxCriticalError() << "Unusual PlanarYCbCrData: " << yuvData.mYSkip << ","
+ << yuvData.mCbSkip << "," << yuvData.mCrSkip << ", "
+ << ySize.width << "," << ySize.height << ", "
+ << cbcrSize.width << "," << cbcrSize.height << ", "
+ << yuvData.mYStride << "," << yuvData.mCbCrStride;
+ return false;
+ }
+
+ gfx::IntSize divisors;
+ switch (yuvData.mChromaSubsampling) {
+ case gfx::ChromaSubsampling::FULL:
+ divisors = gfx::IntSize(1, 1);
+ break;
+ case gfx::ChromaSubsampling::HALF_WIDTH:
+ divisors = gfx::IntSize(2, 1);
+ break;
+ case gfx::ChromaSubsampling::HALF_WIDTH_AND_HEIGHT:
+ divisors = gfx::IntSize(2, 2);
+ break;
+ default:
+ gfxCriticalError() << "Unknown chroma subsampling:"
+ << int(yuvData.mChromaSubsampling);
+ return false;
+ }
+
+ // --
+
+ // RED textures aren't valid in GLES2, and ALPHA textures are not valid in
+ // desktop GL Core Profiles. So use R8 textures on GL3.0+ and GLES3.0+, but
+ // LUMINANCE/LUMINANCE/UNSIGNED_BYTE otherwise.
+ GLenum internalFormat;
+ GLenum unpackFormat;
+ if (mGL->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) ||
+ mGL->IsAtLeast(gl::ContextProfile::OpenGLES, 300)) {
+ internalFormat = LOCAL_GL_R8;
+ unpackFormat = LOCAL_GL_RED;
+ } else {
+ internalFormat = LOCAL_GL_LUMINANCE;
+ unpackFormat = LOCAL_GL_LUMINANCE;
+ }
+
+ // --
+
+ const ScopedSaveMultiTex saveTex(mGL, {0, 1, 2}, LOCAL_GL_TEXTURE_2D);
+ const ResetUnpackState reset(mGL);
+ const gfx::IntSize yTexSize(yuvData.mYStride, yuvData.YDataSize().height);
+ const gfx::IntSize uvTexSize(yuvData.mCbCrStride,
+ yuvData.CbCrDataSize().height);
+
+ if (yTexSize != mYuvUploads_YSize || uvTexSize != mYuvUploads_UVSize) {
+ mYuvUploads_YSize = yTexSize;
+ mYuvUploads_UVSize = uvTexSize;
+
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[0]);
+ mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, internalFormat, yTexSize.width,
+ yTexSize.height, 0, unpackFormat, LOCAL_GL_UNSIGNED_BYTE,
+ nullptr);
+ for (int i = 1; i < 3; i++) {
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[i]);
+ mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, internalFormat, uvTexSize.width,
+ uvTexSize.height, 0, unpackFormat,
+ LOCAL_GL_UNSIGNED_BYTE, nullptr);
+ }
+ }
+
+ // --
+
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[0]);
+ mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, 0, 0, yTexSize.width,
+ yTexSize.height, unpackFormat, LOCAL_GL_UNSIGNED_BYTE,
+ yuvData.mYChannel);
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE1);
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[1]);
+ mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, 0, 0, uvTexSize.width,
+ uvTexSize.height, unpackFormat, LOCAL_GL_UNSIGNED_BYTE,
+ yuvData.mCbChannel);
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE2);
+ mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, mYuvUploads[2]);
+ mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, 0, 0, 0, uvTexSize.width,
+ uvTexSize.height, unpackFormat, LOCAL_GL_UNSIGNED_BYTE,
+ yuvData.mCrChannel);
+
+ // --
+
+ const auto& clipRect = yuvData.mPictureRect;
+ const auto srcOrigin = OriginPos::BottomLeft;
+ const bool yFlip = (destOrigin != srcOrigin);
+
+ const DrawBlitProg::BaseArgs baseArgs = {SubRectMat3(clipRect, yTexSize),
+ yFlip, destSize, Nothing()};
+ const DrawBlitProg::YUVArgs yuvArgs = {
+ SubRectMat3(clipRect, uvTexSize, divisors), Some(yuvData.mYUVColorSpace)};
+ prog->Draw(baseArgs, &yuvArgs);
+ return true;
+}
+
+// -------------------------------------
+
+#ifdef XP_MACOSX
+bool GLBlitHelper::BlitImage(layers::MacIOSurfaceImage* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ return BlitImage(srcImage->GetSurface(), destSize, destOrigin);
+}
+
+static std::string IntAsAscii(const int x) {
+ std::string str;
+ str.reserve(6);
+ auto u = static_cast<unsigned int>(x);
+ while (u) {
+ str.insert(str.begin(), u & 0xff);
+ u >>= 8;
+ }
+ str.insert(str.begin(), '\'');
+ str.push_back('\'');
+ return str;
+}
+
+bool GLBlitHelper::BlitImage(MacIOSurface* const iosurf,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ if (!iosurf) {
+ gfxCriticalError() << "Null MacIOSurface for GLBlitHelper::BlitImage";
+ return false;
+ }
+ if (mGL->GetContextType() != GLContextType::CGL) {
+ MOZ_ASSERT(false);
+ return false;
+ }
+ const auto glCGL = static_cast<GLContextCGL*>(mGL);
+ const auto cglContext = glCGL->GetCGLContext();
+
+ const auto& srcOrigin = OriginPos::BottomLeft;
+
+ DrawBlitProg::BaseArgs baseArgs;
+ baseArgs.yFlip = (destOrigin != srcOrigin);
+ baseArgs.destSize = destSize;
+
+ // TODO: The colorspace is known by the IOSurface, why override it?
+ // See GetYUVColorSpace/GetFullRange()
+ DrawBlitProg::YUVArgs yuvArgs;
+ yuvArgs.colorSpaceForMatrix = Some(iosurf->GetYUVColorSpace());
+
+ const DrawBlitProg::YUVArgs* pYuvArgs = nullptr;
+
+ auto planes = iosurf->GetPlaneCount();
+ if (!planes) {
+ planes = 1; // Bad API. No cookie.
+ }
+
+ const GLenum texTarget = LOCAL_GL_TEXTURE_RECTANGLE;
+
+ std::vector<uint8_t> texUnits;
+ for (uint8_t i = 0; i < planes; i++) {
+ texUnits.push_back(i);
+ }
+ const ScopedSaveMultiTex saveTex(mGL, texUnits, texTarget);
+ const ScopedTexture tex0(mGL);
+ const ScopedTexture tex1(mGL);
+ const ScopedTexture tex2(mGL);
+ const GLuint texs[3] = {tex0, tex1, tex2};
+
+ const auto pixelFormat = iosurf->GetPixelFormat();
+ if (mGL->ShouldSpew()) {
+ const auto formatStr = IntAsAscii(pixelFormat);
+ printf_stderr("iosurf format: %s (0x%08x)\n", formatStr.c_str(),
+ pixelFormat);
+ }
+
+ const char* fragSample;
+ switch (planes) {
+ case 1:
+ switch (pixelFormat) {
+ case kCVPixelFormatType_24RGB:
+ case kCVPixelFormatType_24BGR:
+ case kCVPixelFormatType_32ARGB:
+ case kCVPixelFormatType_32BGRA:
+ case kCVPixelFormatType_32ABGR:
+ case kCVPixelFormatType_32RGBA:
+ case kCVPixelFormatType_64ARGB:
+ case kCVPixelFormatType_48RGB:
+ fragSample = kFragSample_OnePlane;
+ break;
+ case kCVPixelFormatType_422YpCbCr8:
+ case kCVPixelFormatType_422YpCbCr8_yuvs:
+ fragSample = kFragSample_OnePlane_YUV_via_GBR;
+ pYuvArgs = &yuvArgs;
+ break;
+ default: {
+ std::string str;
+ if (pixelFormat <= 0xff) {
+ str = std::to_string(pixelFormat);
+ } else {
+ str = IntAsAscii(pixelFormat);
+ }
+ gfxCriticalError() << "Unhandled kCVPixelFormatType_*: " << str;
+ // Probably YUV though
+ fragSample = kFragSample_OnePlane_YUV_via_GBR;
+ pYuvArgs = &yuvArgs;
+ break;
+ }
+ }
+ break;
+ case 2:
+ fragSample = kFragSample_TwoPlane;
+ pYuvArgs = &yuvArgs;
+ break;
+ case 3:
+ fragSample = kFragSample_ThreePlane;
+ pYuvArgs = &yuvArgs;
+ break;
+ default:
+ gfxCriticalError() << "Unexpected plane count: " << planes;
+ return false;
+ }
+
+ for (uint32_t p = 0; p < planes; p++) {
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + p);
+ mGL->fBindTexture(texTarget, texs[p]);
+ mGL->TexParams_SetClampNoMips(texTarget);
+
+ auto err = iosurf->CGLTexImageIOSurface2D(mGL, cglContext, p);
+ if (err) {
+ return false;
+ }
+
+ if (p == 0) {
+ const auto width = iosurf->GetDevicePixelWidth(p);
+ const auto height = iosurf->GetDevicePixelHeight(p);
+ baseArgs.texMatrix0 = SubRectMat3(0, 0, width, height);
+ yuvArgs.texMatrix1 = SubRectMat3(0, 0, width / 2.0, height / 2.0);
+ }
+ }
+
+ const auto& prog = GetDrawBlitProg({
+ kFragHeader_Tex2DRect,
+ {fragSample, kFragConvert_ColorMatrix},
+ });
+ prog->Draw(baseArgs, pYuvArgs);
+ return true;
+}
+#endif
+
+// -----------------------------------------------------------------------------
+
+void GLBlitHelper::DrawBlitTextureToFramebuffer(const GLuint srcTex,
+ const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ const GLenum srcTarget,
+ const bool srcIsBGRA) const {
+ const char* fragHeader = nullptr;
+ Mat3 texMatrix0;
+ switch (srcTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ fragHeader = kFragHeader_Tex2D;
+ texMatrix0 = Mat3::I();
+ break;
+ case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
+ fragHeader = kFragHeader_Tex2DRect;
+ texMatrix0 = SubRectMat3(0, 0, srcSize.width, srcSize.height);
+ break;
+ default:
+ gfxCriticalError() << "Unexpected srcTarget: " << srcTarget;
+ return;
+ }
+ const auto fragConvert = srcIsBGRA ? kFragConvert_BGR : kFragConvert_None;
+ const auto& prog = GetDrawBlitProg({
+ fragHeader,
+ {kFragSample_OnePlane, fragConvert},
+ });
+
+ const ScopedSaveMultiTex saveTex(mGL, {0}, srcTarget);
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
+ mGL->fBindTexture(srcTarget, srcTex);
+
+ const bool yFlip = false;
+ const DrawBlitProg::BaseArgs baseArgs = {texMatrix0, yFlip, destSize,
+ Nothing()};
+ prog->Draw(baseArgs);
+}
+
+// -----------------------------------------------------------------------------
+
+void GLBlitHelper::BlitFramebuffer(const gfx::IntRect& srcRect,
+ const gfx::IntRect& destRect,
+ GLuint filter) const {
+ MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit));
+
+ const ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
+ mGL->fBlitFramebuffer(srcRect.x, srcRect.y, srcRect.XMost(), srcRect.YMost(),
+ destRect.x, destRect.y, destRect.XMost(),
+ destRect.YMost(), LOCAL_GL_COLOR_BUFFER_BIT, filter);
+}
+
+// --
+
+void GLBlitHelper::BlitFramebufferToFramebuffer(const GLuint srcFB,
+ const GLuint destFB,
+ const gfx::IntRect& srcRect,
+ const gfx::IntRect& destRect,
+ GLuint filter) const {
+ MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit));
+ MOZ_GL_ASSERT(mGL, !srcFB || mGL->fIsFramebuffer(srcFB));
+ MOZ_GL_ASSERT(mGL, !destFB || mGL->fIsFramebuffer(destFB));
+
+ const ScopedBindFramebuffer boundFB(mGL);
+ mGL->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, srcFB);
+ mGL->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, destFB);
+
+ BlitFramebuffer(srcRect, destRect, filter);
+}
+
+void GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex,
+ const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum srcTarget) const {
+ MOZ_GL_ASSERT(mGL, mGL->fIsTexture(srcTex));
+
+ if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
+ const ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
+ const ScopedBindFramebuffer bindFB(mGL);
+ mGL->fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER, srcWrapper.FB());
+ BlitFramebuffer(gfx::IntRect({}, srcSize), gfx::IntRect({}, destSize));
+ return;
+ }
+
+ DrawBlitTextureToFramebuffer(srcTex, srcSize, destSize, srcTarget);
+}
+
+void GLBlitHelper::BlitFramebufferToTexture(GLuint destTex,
+ const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum destTarget) const {
+ MOZ_GL_ASSERT(mGL, mGL->fIsTexture(destTex));
+
+ if (mGL->IsSupported(GLFeature::framebuffer_blit)) {
+ const ScopedFramebufferForTexture destWrapper(mGL, destTex, destTarget);
+ const ScopedBindFramebuffer bindFB(mGL);
+ mGL->fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER, destWrapper.FB());
+ BlitFramebuffer(gfx::IntRect({}, srcSize), gfx::IntRect({}, destSize));
+ return;
+ }
+
+ ScopedBindTexture autoTex(mGL, destTex, destTarget);
+ ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false);
+ mGL->fCopyTexSubImage2D(destTarget, 0, 0, 0, 0, 0, srcSize.width,
+ srcSize.height);
+}
+
+void GLBlitHelper::BlitTextureToTexture(GLuint srcTex, GLuint destTex,
+ const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum srcTarget,
+ GLenum destTarget) const {
+ MOZ_GL_ASSERT(mGL, mGL->fIsTexture(srcTex));
+ MOZ_GL_ASSERT(mGL, mGL->fIsTexture(destTex));
+
+ // Start down the CopyTexSubImage path, not the DrawBlit path.
+ const ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget);
+ const ScopedBindFramebuffer bindFB(mGL, srcWrapper.FB());
+ BlitFramebufferToTexture(destTex, srcSize, destSize, destTarget);
+}
+
+// -------------------------------------
+
+bool GLBlitHelper::BlitImage(layers::GPUVideoImage* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& data = srcImage->GetData();
+ if (!data) return false;
+
+ const auto& desc = data->SD();
+
+ MOZ_ASSERT(
+ desc.type() ==
+ layers::SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder);
+ const auto& subdescUnion =
+ desc.get_SurfaceDescriptorRemoteDecoder().subdesc();
+ switch (subdescUnion.type()) {
+#ifdef MOZ_WIDGET_GTK
+ case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorDMABuf: {
+ const auto& subdesc = subdescUnion.get_SurfaceDescriptorDMABuf();
+ RefPtr<DMABufSurface> surface =
+ DMABufSurface::CreateDMABufSurface(subdesc);
+ return Blit(surface, destSize, destOrigin);
+ }
+#endif
+#ifdef XP_WIN
+ case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorD3D10: {
+ const auto& subdesc = subdescUnion.get_SurfaceDescriptorD3D10();
+ return BlitDescriptor(subdesc, destSize, destOrigin);
+ }
+ case layers::RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorDXGIYCbCr: {
+ const auto& subdesc = subdescUnion.get_SurfaceDescriptorDXGIYCbCr();
+ return BlitDescriptor(subdesc, destSize, destOrigin);
+ }
+#endif
+#ifdef XP_MACOSX
+ case layers::RemoteDecoderVideoSubDescriptor::
+ TSurfaceDescriptorMacIOSurface: {
+ const auto& subdesc = subdescUnion.get_SurfaceDescriptorMacIOSurface();
+ RefPtr<MacIOSurface> surface = MacIOSurface::LookupSurface(
+ subdesc.surfaceId(), !subdesc.isOpaque(), subdesc.yUVColorSpace());
+ MOZ_ASSERT(surface);
+ if (!surface) {
+ return false;
+ }
+ return BlitImage(surface, destSize, destOrigin);
+ }
+#endif
+ case layers::RemoteDecoderVideoSubDescriptor::Tnull_t:
+ // This GPUVideoImage isn't directly readable outside the GPU process.
+ // Abort.
+ return false;
+ default:
+ gfxCriticalError() << "Unhandled subdesc type: "
+ << uint32_t(subdescUnion.type());
+ return false;
+ }
+}
+
+// -------------------------------------
+#ifdef MOZ_WIDGET_GTK
+bool GLBlitHelper::Blit(DMABufSurface* surface, const gfx::IntSize& destSize,
+ OriginPos destOrigin) const {
+ const auto& srcOrigin = OriginPos::BottomLeft;
+
+ DrawBlitProg::BaseArgs baseArgs;
+ baseArgs.yFlip = (destOrigin != srcOrigin);
+ baseArgs.destSize = destSize;
+
+ // TODO: The colorspace is known by the DMABUFSurface, why override it?
+ // See GetYUVColorSpace/GetFullRange()
+ DrawBlitProg::YUVArgs yuvArgs;
+ yuvArgs.colorSpaceForMatrix = Some(surface->GetYUVColorSpace());
+
+ const DrawBlitProg::YUVArgs* pYuvArgs = nullptr;
+ const auto planes = surface->GetTextureCount();
+
+ // -
+ // Ensure textures for all planes have been created.
+
+ const bool createTextures = [&]() {
+ for (int i = 0; i < planes; i++) {
+ if (!surface->GetTexture(i)) {
+ return true;
+ }
+ }
+ return false;
+ }();
+
+ bool didCreateTexture = false;
+ auto releaseTextures = mozilla::MakeScopeExit([&] {
+ if (didCreateTexture) {
+ surface->ReleaseTextures();
+ }
+ });
+
+ if (createTextures) {
+ for (int i = 0; i < planes; i++) {
+ if (surface->GetTexture(i)) {
+ continue;
+ }
+ if (!surface->CreateTexture(mGL, i)) {
+ LOGDMABUF(("GLBlitHelper::Blit(): Failed to create DMABuf textures."));
+ return false;
+ }
+ didCreateTexture = true;
+ }
+ }
+
+ // -
+
+ const GLenum texTarget = LOCAL_GL_TEXTURE_2D;
+
+ std::vector<uint8_t> texUnits;
+ for (uint8_t i = 0; i < planes; i++) {
+ texUnits.push_back(i);
+ }
+ const ScopedSaveMultiTex saveTex(mGL, texUnits, texTarget);
+ const auto pixelFormat = surface->GetSurfaceType();
+
+ const char* fragSample;
+ auto fragConvert = kFragConvert_None;
+ switch (pixelFormat) {
+ case DMABufSurface::SURFACE_RGBA:
+ fragSample = kFragSample_OnePlane;
+ break;
+ case DMABufSurface::SURFACE_NV12:
+ fragSample = kFragSample_TwoPlane;
+ pYuvArgs = &yuvArgs;
+ fragConvert = kFragConvert_ColorMatrix;
+ break;
+ case DMABufSurface::SURFACE_YUV420:
+ fragSample = kFragSample_ThreePlane;
+ pYuvArgs = &yuvArgs;
+ fragConvert = kFragConvert_ColorMatrix;
+ break;
+ default:
+ gfxCriticalError() << "Unexpected pixel format: " << pixelFormat;
+ return false;
+ }
+
+ for (const auto p : IntegerRange(planes)) {
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + p);
+ mGL->fBindTexture(texTarget, surface->GetTexture(p));
+ mGL->TexParams_SetClampNoMips(texTarget);
+ }
+
+ // We support only NV12/YUV420 formats only with 1/2 texture scale.
+ // We don't set cliprect as DMABus textures are created without padding.
+ baseArgs.texMatrix0 = SubRectMat3(0, 0, 1, 1);
+ yuvArgs.texMatrix1 = SubRectMat3(0, 0, 1, 1);
+
+ const auto& prog =
+ GetDrawBlitProg({kFragHeader_Tex2D, {fragSample, fragConvert}});
+ prog->Draw(baseArgs, pYuvArgs);
+
+ return true;
+}
+
+bool GLBlitHelper::BlitImage(layers::DMABUFSurfaceImage* srcImage,
+ const gfx::IntSize& destSize,
+ OriginPos destOrigin) const {
+ DMABufSurface* surface = srcImage->GetSurface();
+ if (!surface) {
+ gfxCriticalError() << "Null DMABUFSurface for GLBlitHelper::BlitImage";
+ return false;
+ }
+ return Blit(surface, destSize, destOrigin);
+}
+#endif
+
+// -
+
+template <size_t N>
+static void PushUnorm(uint32_t* const out, const float inVal) {
+ const uint32_t mask = (1 << N) - 1;
+ auto fval = inVal;
+ fval = std::max(0.0f, std::min(fval, 1.0f));
+ fval *= mask;
+ fval = roundf(fval);
+ auto ival = static_cast<uint32_t>(fval);
+ ival &= mask;
+
+ *out <<= N;
+ *out |= ival;
+}
+
+static uint32_t toRgb10A2(const color::vec4& val) {
+ // R in LSB
+ uint32_t ret = 0;
+ PushUnorm<2>(&ret, val.w());
+ PushUnorm<10>(&ret, val.z());
+ PushUnorm<10>(&ret, val.y());
+ PushUnorm<10>(&ret, val.x());
+ return ret;
+}
+
+std::shared_ptr<gl::Texture> GLBlitHelper::GetColorLutTex(
+ const ColorLutKey& key) const {
+ auto& weak = mColorLutTexMap[key];
+ auto strong = weak.lock();
+ if (!strong) {
+ auto& gl = *mGL;
+ strong = std::make_shared<gl::Texture>(gl);
+ weak = strong;
+
+ const auto ct = color::ColorspaceTransform::Create(key.src, key.dst);
+
+ // -
+
+ const auto minLutSize = color::ivec3{2};
+ const auto maxLutSize = color::ivec3{256};
+ auto lutSize = minLutSize;
+ if (ct.srcSpace.yuv) {
+ lutSize.x(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_y()));
+ lutSize.y(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_cb()));
+ lutSize.z(int(StaticPrefs::gfx_blithelper_lut_size_ycbcr_cr()));
+ } else {
+ lutSize.x(int(StaticPrefs::gfx_blithelper_lut_size_rgb_r()));
+ lutSize.y(int(StaticPrefs::gfx_blithelper_lut_size_rgb_g()));
+ lutSize.z(int(StaticPrefs::gfx_blithelper_lut_size_rgb_b()));
+ }
+ lutSize = max(minLutSize, min(lutSize, maxLutSize)); // Clamp
+
+ const auto lut = ct.ToLut3(lutSize);
+ const auto& size = lut.size;
+
+ // -
+
+ constexpr GLenum target = LOCAL_GL_TEXTURE_3D;
+ const auto bind = gl::ScopedBindTexture(&gl, strong->name, target);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+
+ bool useFloat16 = true;
+ if (useFloat16) {
+ // Use rgba16f, which we can thankfully upload as rgba32f
+ static_assert(sizeof(color::vec4) == sizeof(float) * 4);
+ std::vector<color::vec4> uploadData;
+ uploadData.reserve(lut.data.size());
+ for (const auto& src : lut.data) {
+ const auto dst = color::vec4{src, 1};
+ uploadData.push_back(dst);
+ }
+
+ gl.fTexStorage3D(target, 1, LOCAL_GL_RGBA16F, size.x(), size.y(),
+ size.z());
+ gl.fTexSubImage3D(target, 0, 0, 0, 0, size.x(), size.y(), size.z(),
+ LOCAL_GL_RGBA, LOCAL_GL_FLOAT, uploadData.data());
+ } else {
+ // Use Rgb10A2
+ std::vector<uint32_t> uploadData;
+ uploadData.reserve(lut.data.size());
+ for (const auto& src : lut.data) {
+ const auto dst = toRgb10A2({src, 1});
+ uploadData.push_back(dst);
+ }
+
+ gl.fTexStorage3D(target, 1, LOCAL_GL_RGB10_A2, size.x(), size.y(),
+ size.z());
+ gl.fTexSubImage3D(target, 0, 0, 0, 0, size.x(), size.y(), size.z(),
+ LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV,
+ uploadData.data());
+ }
+ }
+ return strong;
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLBlitHelper.h b/gfx/gl/GLBlitHelper.h
new file mode 100644
index 0000000000..8391509097
--- /dev/null
+++ b/gfx/gl/GLBlitHelper.h
@@ -0,0 +1,338 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLBLITHELPER_H_
+#define GLBLITHELPER_H_
+
+#include <array>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <unordered_map>
+#include "Colorspaces.h"
+#include "GLConsts.h"
+#include "GLContextTypes.h"
+#include "GLTypes.h"
+#include "nsSize.h"
+#include "nsString.h"
+#include "nsTString.h"
+#include "mozilla/ipc/IPCTypes.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/gfx/Types.h"
+
+#include <map>
+
+#ifdef XP_WIN
+# include <windows.h>
+# include "mozilla/RefPtr.h"
+# include "mozilla/ipc/IPCTypes.h"
+struct ID3D11Device;
+struct ID3D11Texture2D;
+#endif
+
+#ifdef XP_MACOSX
+class MacIOSurface;
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/java/GeckoSurfaceTextureWrappers.h"
+#endif
+
+#ifdef MOZ_WIDGET_GTK
+class DMABufSurface;
+#endif
+
+namespace mozilla {
+
+namespace layers {
+class Image;
+class GPUVideoImage;
+struct PlanarYCbCrData;
+class PlanarYCbCrImage;
+class SurfaceDescriptor;
+class SurfaceDescriptorBuffer;
+
+#ifdef XP_WIN
+class D3D11ShareHandleImage;
+class D3D11TextureIMFSampleImage;
+class D3D11YCbCrImage;
+class SurfaceDescriptorD3D10;
+class SurfaceDescriptorDXGIYCbCr;
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+class SurfaceTextureDescriptor;
+#endif
+
+#ifdef XP_MACOSX
+class MacIOSurfaceImage;
+#endif
+
+#ifdef MOZ_WIDGET_GTK
+class DMABUFSurfaceImage;
+#endif
+} // namespace layers
+
+namespace gl {
+
+class BindAnglePlanes;
+class GLBlitHelper;
+class GLContext;
+class Texture;
+
+bool GuessDivisors(const gfx::IntSize& ySize, const gfx::IntSize& uvSize,
+ gfx::IntSize* const out_divisors);
+
+template <uint8_t N>
+struct Mat {
+ float m[N * N]; // column-major, for GL
+
+ float& at(const uint8_t x, const uint8_t y) { return m[N * x + y]; }
+
+ static Mat<N> I() {
+ auto ret = Mat<N>{};
+ for (uint8_t i = 0; i < N; i++) {
+ ret.at(i, i) = 1.0f;
+ }
+ return ret;
+ }
+
+ Mat<N> operator*(const Mat<N>& r) const {
+ Mat<N> ret;
+ for (uint8_t x = 0; x < N; x++) {
+ for (uint8_t y = 0; y < N; y++) {
+ float sum = 0.0f;
+ for (uint8_t i = 0; i < N; i++) {
+ sum += at(i, y) * r.at(x, i);
+ }
+ ret.at(x, y) = sum;
+ }
+ }
+ return ret;
+ }
+};
+typedef Mat<3> Mat3;
+
+Mat3 SubRectMat3(float x, float y, float w, float h);
+Mat3 SubRectMat3(const gfx::IntRect& subrect, const gfx::IntSize& size);
+Mat3 SubRectMat3(const gfx::IntRect& bigSubrect, const gfx::IntSize& smallSize,
+ const gfx::IntSize& divisors);
+
+class DrawBlitProg final {
+ const GLBlitHelper& mParent;
+ const GLuint mProg;
+ const GLint mLoc_uDestMatrix;
+ const GLint mLoc_uTexMatrix0;
+ const GLint mLoc_uTexMatrix1;
+ const GLint mLoc_uColorLut;
+ const GLint mLoc_uColorMatrix;
+ GLenum mType_uColorMatrix = 0;
+
+ public:
+ struct Key final {
+ const char* fragHeader = nullptr;
+ std::array<const char*, 4> fragParts = {};
+
+ auto Members() const { return std::tie(fragHeader, fragParts); }
+ friend bool operator<(const Key& a, const Key& b) {
+ return a.Members() < b.Members();
+ }
+ };
+
+ DrawBlitProg(const GLBlitHelper* parent, GLuint prog);
+ ~DrawBlitProg();
+
+ struct BaseArgs final {
+ Mat3 texMatrix0;
+ bool yFlip;
+ gfx::IntSize
+ destSize; // Always needed for (at least) setting the viewport.
+ Maybe<gfx::IntRect> destRect;
+ Maybe<uint32_t> texUnitForColorLut;
+ };
+ struct YUVArgs final {
+ Mat3 texMatrix1;
+ Maybe<gfx::YUVColorSpace> colorSpaceForMatrix;
+ };
+
+ void Draw(const BaseArgs& args, const YUVArgs* argsYUV = nullptr) const;
+};
+
+class ScopedSaveMultiTex final {
+ GLContext& mGL;
+ const std::vector<uint8_t> mTexUnits;
+ const GLenum mTexTarget;
+ const GLuint mOldTexUnit;
+ GLuint mOldTexSampler[3];
+ GLuint mOldTex[3];
+
+ public:
+ ScopedSaveMultiTex(GLContext* gl, const std::vector<uint8_t>& texUnits,
+ GLenum texTarget);
+ ~ScopedSaveMultiTex();
+};
+
+/** Buffer blitting helper */
+class GLBlitHelper final {
+ friend class BindAnglePlanes;
+ friend class DrawBlitProg;
+ friend class GLContext;
+
+ GLContext* const mGL;
+ mutable std::map<DrawBlitProg::Key, const DrawBlitProg*> mDrawBlitProgs;
+
+ GLuint mQuadVAO = 0;
+ GLuint mQuadVBO = 0;
+ nsCString mDrawBlitProg_VersionLine;
+ const GLuint mDrawBlitProg_VertShader;
+
+ GLuint mYuvUploads[3] = {};
+ gfx::IntSize mYuvUploads_YSize = {0, 0};
+ gfx::IntSize mYuvUploads_UVSize = {0, 0};
+
+ public:
+ struct ColorLutKey {
+ color::ColorspaceDesc src;
+ color::ColorspaceDesc dst;
+
+ auto Members() const { return std::tie(src, dst); }
+ INLINE_AUTO_MAPPABLE(ColorLutKey)
+ };
+
+ private:
+ mutable std::unordered_map<ColorLutKey, std::weak_ptr<gl::Texture>,
+ ColorLutKey::Hasher>
+ mColorLutTexMap;
+
+ public:
+ std::shared_ptr<gl::Texture> GetColorLutTex(const ColorLutKey& key) const;
+
+#ifdef XP_WIN
+ mutable RefPtr<ID3D11Device> mD3D11;
+
+ ID3D11Device* GetD3D11() const;
+#endif
+
+ const DrawBlitProg* GetDrawBlitProg(const DrawBlitProg::Key& key) const;
+
+ private:
+ const DrawBlitProg* CreateDrawBlitProg(const DrawBlitProg::Key& key) const;
+
+ public:
+ bool BlitPlanarYCbCr(const layers::PlanarYCbCrData&,
+ const gfx::IntSize& destSize, OriginPos destOrigin);
+#ifdef MOZ_WIDGET_ANDROID
+ bool Blit(const java::GeckoSurfaceTexture::Ref& surfaceTexture,
+ const gfx::IntSize& destSize, const OriginPos destOrigin) const;
+#endif
+#ifdef XP_MACOSX
+ bool BlitImage(layers::MacIOSurfaceImage* srcImage,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+#endif
+#ifdef MOZ_WIDGET_GTK
+ bool Blit(DMABufSurface* surface, const gfx::IntSize& destSize,
+ OriginPos destOrigin) const;
+ bool BlitImage(layers::DMABUFSurfaceImage* srcImage,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+#endif
+
+ explicit GLBlitHelper(GLContext* gl);
+
+ public:
+ ~GLBlitHelper();
+
+ void BlitFramebuffer(const gfx::IntRect& srcRect,
+ const gfx::IntRect& destRect,
+ GLuint filter = LOCAL_GL_NEAREST) const;
+ void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB,
+ const gfx::IntRect& srcRect,
+ const gfx::IntRect& destRect,
+ GLuint filter = LOCAL_GL_NEAREST) const;
+ void BlitFramebufferToTexture(GLuint destTex, const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
+ void BlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum srcTarget = LOCAL_GL_TEXTURE_2D) const;
+ void BlitTextureToTexture(GLuint srcTex, GLuint destTex,
+ const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
+ GLenum destTarget = LOCAL_GL_TEXTURE_2D) const;
+
+ void DrawBlitTextureToFramebuffer(GLuint srcTex, const gfx::IntSize& srcSize,
+ const gfx::IntSize& destSize,
+ GLenum srcTarget = LOCAL_GL_TEXTURE_2D,
+ bool srcIsBGRA = false) const;
+
+ bool BlitImageToFramebuffer(layers::Image* srcImage,
+ const gfx::IntSize& destSize,
+ OriginPos destOrigin);
+ bool BlitSdToFramebuffer(const layers::SurfaceDescriptor&,
+ const gfx::IntSize& destSize, OriginPos destOrigin);
+
+ private:
+ bool BlitImage(layers::GPUVideoImage* srcImage, const gfx::IntSize& destSize,
+ OriginPos destOrigin) const;
+#ifdef XP_MACOSX
+ bool BlitImage(MacIOSurface* const iosurf, const gfx::IntSize& destSize,
+ OriginPos destOrigin) const;
+#endif
+#ifdef XP_WIN
+ // GLBlitHelperD3D.cpp:
+ bool BlitImage(layers::D3D11ShareHandleImage* srcImage,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+ bool BlitImage(layers::D3D11TextureIMFSampleImage* srcImage,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+ bool BlitImage(layers::D3D11YCbCrImage* srcImage,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+
+ bool BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+ bool BlitDescriptor(const layers::SurfaceDescriptorDXGIYCbCr& desc,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const;
+ bool BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
+ const gfx::IntRect& clipRect, const gfx::IntSize& ySize,
+ const gfx::IntSize& uvSize,
+ const gfx::YUVColorSpace colorSpace,
+ const gfx::IntSize& destSize, OriginPos destOrigin) const;
+
+ bool BlitAnglePlanes(uint8_t numPlanes,
+ const RefPtr<ID3D11Texture2D>* texD3DList,
+ const DrawBlitProg* prog,
+ const DrawBlitProg::BaseArgs& baseArgs,
+ const DrawBlitProg::YUVArgs* const yuvArgs) const;
+#endif
+};
+
+// -
+// For DrawBlitProg::Key::fragParts
+
+extern const char* const kFragHeader_Tex2D;
+extern const char* const kFragHeader_Tex2DRect;
+extern const char* const kFragHeader_TexExt;
+
+extern const char* const kFragSample_OnePlane;
+extern const char* const kFragSample_TwoPlane;
+extern const char* const kFragSample_ThreePlane;
+
+extern const char* const kFragConvert_None;
+extern const char* const kFragConvert_BGR;
+extern const char* const kFragConvert_ColorMatrix;
+extern const char* const kFragConvert_ColorLut;
+
+extern const char* const kFragMixin_AlphaMultColors;
+extern const char* const kFragMixin_AlphaClampColors;
+extern const char* const kFragMixin_AlphaOne;
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLBLITHELPER_H_
diff --git a/gfx/gl/GLBlitHelperD3D.cpp b/gfx/gl/GLBlitHelperD3D.cpp
new file mode 100644
index 0000000000..ae6362e278
--- /dev/null
+++ b/gfx/gl/GLBlitHelperD3D.cpp
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLBlitHelper.h"
+
+#include <d3d11.h>
+#include <d3d11_1.h>
+
+#include "GLContextEGL.h"
+#include "GLLibraryEGL.h"
+#include "GPUVideoImage.h"
+#include "ScopedGLHelpers.h"
+
+#include "mozilla/layers/D3D11ShareHandleImage.h"
+#include "mozilla/layers/D3D11TextureIMFSampleImage.h"
+#include "mozilla/layers/D3D11YCbCrImage.h"
+#include "mozilla/layers/GpuProcessD3D11TextureMap.h"
+#include "mozilla/layers/TextureD3D11.h"
+#include "mozilla/StaticPrefs_gl.h"
+
+namespace mozilla {
+namespace gl {
+
+#define NOTE_IF_FALSE(expr) \
+ do { \
+ if (!(expr)) { \
+ gfxCriticalNote << "NOTE_IF_FALSE: " << #expr; \
+ } \
+ } while (false)
+
+static EGLStreamKHR StreamFromD3DTexture(EglDisplay* const egl,
+ ID3D11Texture2D* const texD3D,
+ const EGLAttrib* const postAttribs) {
+ if (!egl->IsExtensionSupported(
+ EGLExtension::NV_stream_consumer_gltexture_yuv) ||
+ !egl->IsExtensionSupported(
+ EGLExtension::ANGLE_stream_producer_d3d_texture)) {
+ return 0;
+ }
+
+ const auto stream = egl->fCreateStreamKHR(nullptr);
+ MOZ_ASSERT(stream);
+ if (!stream) return 0;
+ bool ok = true;
+ NOTE_IF_FALSE(ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
+ stream, nullptr)));
+ NOTE_IF_FALSE(
+ ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(stream, nullptr)));
+ NOTE_IF_FALSE(
+ ok &= bool(egl->fStreamPostD3DTextureANGLE(stream, texD3D, postAttribs)));
+ if (ok) return stream;
+
+ (void)egl->fDestroyStreamKHR(stream);
+ return 0;
+}
+
+static RefPtr<ID3D11Texture2D> OpenSharedTexture(ID3D11Device* const d3d,
+ const WindowsHandle handle) {
+ RefPtr<ID3D11Device1> device1;
+ d3d->QueryInterface((ID3D11Device1**)getter_AddRefs(device1));
+ if (!device1) {
+ gfxCriticalNoteOnce << "Failed to get ID3D11Device1";
+ return nullptr;
+ }
+
+ RefPtr<ID3D11Texture2D> tex;
+ auto hr = device1->OpenSharedResource1(
+ (HANDLE)handle, __uuidof(ID3D11Texture2D),
+ (void**)(ID3D11Texture2D**)getter_AddRefs(tex));
+ if (FAILED(hr)) {
+ gfxCriticalError() << "Error code from OpenSharedResource1: "
+ << gfx::hexa(hr);
+ return nullptr;
+ }
+ return tex;
+}
+
+// -------------------------------------
+
+class BindAnglePlanes final {
+ const GLBlitHelper& mParent;
+ const uint8_t mNumPlanes;
+ const ScopedSaveMultiTex mMultiTex;
+ GLuint mTempTexs[3];
+ EGLStreamKHR mStreams[3];
+ RefPtr<IDXGIKeyedMutex> mMutexList[3];
+ bool mSuccess;
+
+ public:
+ BindAnglePlanes(const GLBlitHelper* const parent, const uint8_t numPlanes,
+ const RefPtr<ID3D11Texture2D>* const texD3DList,
+ const EGLAttrib* const* postAttribsList = nullptr)
+ : mParent(*parent),
+ mNumPlanes(numPlanes),
+ mMultiTex(
+ mParent.mGL,
+ [&]() {
+ std::vector<uint8_t> ret;
+ for (int i = 0; i < numPlanes; i++) {
+ ret.push_back(i);
+ }
+ return ret;
+ }(),
+ LOCAL_GL_TEXTURE_EXTERNAL),
+ mTempTexs{0},
+ mStreams{0},
+ mSuccess(true) {
+ MOZ_RELEASE_ASSERT(numPlanes >= 1 && numPlanes <= 3);
+
+ const auto& gl = mParent.mGL;
+ const auto& gle = GLContextEGL::Cast(gl);
+ const auto& egl = gle->mEgl;
+
+ gl->fGenTextures(numPlanes, mTempTexs);
+
+ for (uint8_t i = 0; i < mNumPlanes; i++) {
+ gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
+ gl->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, mTempTexs[i]);
+ const EGLAttrib* postAttribs = nullptr;
+ if (postAttribsList) {
+ postAttribs = postAttribsList[i];
+ }
+ mStreams[i] = StreamFromD3DTexture(egl.get(), texD3DList[i], postAttribs);
+ mSuccess &= bool(mStreams[i]);
+ }
+
+ if (mSuccess) {
+ for (uint8_t i = 0; i < mNumPlanes; i++) {
+ NOTE_IF_FALSE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
+
+ auto& mutex = mMutexList[i];
+ texD3DList[i]->QueryInterface(IID_IDXGIKeyedMutex,
+ (void**)getter_AddRefs(mutex));
+ if (mutex) {
+ const auto hr = mutex->AcquireSync(0, 100);
+ if (FAILED(hr)) {
+ NS_WARNING("BindAnglePlanes failed to acquire KeyedMutex.");
+ mSuccess = false;
+ }
+ }
+ }
+ }
+ }
+
+ ~BindAnglePlanes() {
+ const auto& gl = mParent.mGL;
+ const auto& gle = GLContextEGL::Cast(gl);
+ const auto& egl = gle->mEgl;
+
+ if (mSuccess) {
+ for (uint8_t i = 0; i < mNumPlanes; i++) {
+ NOTE_IF_FALSE(egl->fStreamConsumerReleaseKHR(mStreams[i]));
+ if (mMutexList[i]) {
+ mMutexList[i]->ReleaseSync(0);
+ }
+ }
+ }
+
+ for (uint8_t i = 0; i < mNumPlanes; i++) {
+ (void)egl->fDestroyStreamKHR(mStreams[i]);
+ }
+
+ gl->fDeleteTextures(mNumPlanes, mTempTexs);
+ }
+
+ const bool& Success() const { return mSuccess; }
+};
+
+// -------------------------------------
+
+ID3D11Device* GLBlitHelper::GetD3D11() const {
+ if (mD3D11) return mD3D11;
+
+ if (!mGL->IsANGLE()) return nullptr;
+
+ const auto& gle = GLContextEGL::Cast(mGL);
+ const auto& egl = gle->mEgl;
+ EGLDeviceEXT deviceEGL = 0;
+ NOTE_IF_FALSE(egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT,
+ (EGLAttrib*)&deviceEGL));
+ ID3D11Device* device = nullptr;
+ // ANGLE does not `AddRef` its returned pointer for `QueryDeviceAttrib`, so no
+ // `getter_AddRefs`.
+ if (!egl->mLib->fQueryDeviceAttribEXT(deviceEGL, LOCAL_EGL_D3D11_DEVICE_ANGLE,
+ (EGLAttrib*)&device)) {
+ MOZ_ASSERT(false, "d3d9?");
+ return nullptr;
+ }
+ mD3D11 = device;
+ return mD3D11;
+}
+
+// -------------------------------------
+
+bool GLBlitHelper::BlitImage(layers::D3D11ShareHandleImage* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& data = srcImage->GetData();
+ if (!data) return false;
+
+ layers::SurfaceDescriptorD3D10 desc;
+ if (!data->SerializeSpecific(&desc)) return false;
+
+ return BlitDescriptor(desc, destSize, destOrigin);
+}
+
+// -------------------------------------
+
+bool GLBlitHelper::BlitImage(layers::D3D11TextureIMFSampleImage* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& data = srcImage->GetData();
+ if (!data) return false;
+
+ layers::SurfaceDescriptorD3D10 desc;
+ if (!data->SerializeSpecific(&desc)) return false;
+
+ return BlitDescriptor(desc, destSize, destOrigin);
+}
+
+// -------------------------------------
+
+bool GLBlitHelper::BlitImage(layers::D3D11YCbCrImage* const srcImage,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& data = srcImage->GetData();
+ if (!data) return false;
+
+ const WindowsHandle handles[3] = {
+ (WindowsHandle)(data->mHandles[0] ? data->mHandles[0]->GetHandle()
+ : nullptr),
+ (WindowsHandle)(data->mHandles[1] ? data->mHandles[1]->GetHandle()
+ : nullptr),
+ (WindowsHandle)(data->mHandles[2] ? data->mHandles[2]->GetHandle()
+ : nullptr)};
+ return BlitAngleYCbCr(handles, srcImage->mPictureRect, srcImage->GetYSize(),
+ srcImage->GetCbCrSize(), srcImage->mColorSpace,
+ destSize, destOrigin);
+}
+
+// -------------------------------------
+
+bool GLBlitHelper::BlitDescriptor(const layers::SurfaceDescriptorD3D10& desc,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& d3d = GetD3D11();
+ if (!d3d) return false;
+
+ const auto& gpuProcessTextureId = desc.gpuProcessTextureId();
+ const auto& arrayIndex = desc.arrayIndex();
+ const auto& format = desc.format();
+ const auto& clipSize = desc.size();
+
+ const auto srcOrigin = OriginPos::BottomLeft;
+ const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
+ const auto colorSpace = desc.colorSpace();
+
+ if (format != gfx::SurfaceFormat::NV12 &&
+ format != gfx::SurfaceFormat::P010 &&
+ format != gfx::SurfaceFormat::P016) {
+ gfxCriticalError() << "Non-NV12 format for SurfaceDescriptorD3D10: "
+ << uint32_t(format);
+ return false;
+ }
+
+ RefPtr<ID3D11Texture2D> tex;
+ if (gpuProcessTextureId.isSome()) {
+ auto* textureMap = layers::GpuProcessD3D11TextureMap::Get();
+ if (textureMap) {
+ Maybe<HANDLE> handle =
+ textureMap->GetSharedHandleOfCopiedTexture(gpuProcessTextureId.ref());
+ if (handle.isSome()) {
+ tex = OpenSharedTexture(d3d, (WindowsHandle)handle.ref());
+ }
+ }
+ } else if (desc.handle()) {
+ tex = OpenSharedTexture(d3d, (WindowsHandle)desc.handle()->GetHandle());
+ }
+ if (!tex) {
+ MOZ_GL_ASSERT(mGL, false); // Get a nullptr from OpenSharedResource1.
+ return false;
+ }
+ const RefPtr<ID3D11Texture2D> texList[2] = {tex, tex};
+ const EGLAttrib postAttribs0[] = {LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0,
+ LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
+ static_cast<EGLAttrib>(arrayIndex),
+ LOCAL_EGL_NONE};
+ const EGLAttrib postAttribs1[] = {LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 1,
+ LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE,
+ static_cast<EGLAttrib>(arrayIndex),
+ LOCAL_EGL_NONE};
+ const EGLAttrib* const postAttribsList[2] = {postAttribs0, postAttribs1};
+ // /layers/d3d11/CompositorD3D11.cpp uses bt601 for EffectTypes::NV12.
+ // return BlitAngleNv12(tex, YUVColorSpace::BT601, destSize, destOrigin);
+
+ const BindAnglePlanes bindPlanes(this, 2, texList, postAttribsList);
+ if (!bindPlanes.Success()) {
+ MOZ_GL_ASSERT(mGL, false); // BindAnglePlanes failed.
+ return false;
+ }
+
+ D3D11_TEXTURE2D_DESC texDesc = {0};
+ tex->GetDesc(&texDesc);
+
+ const gfx::IntSize ySize(texDesc.Width, texDesc.Height);
+ const gfx::IntSize divisors(2, 2);
+ MOZ_ASSERT(ySize.width % divisors.width == 0);
+ MOZ_ASSERT(ySize.height % divisors.height == 0);
+ const gfx::IntSize uvSize(ySize.width / divisors.width,
+ ySize.height / divisors.height);
+
+ const auto yuvColorSpace = [&]() {
+ switch (colorSpace) {
+ case gfx::ColorSpace2::UNKNOWN:
+ case gfx::ColorSpace2::SRGB:
+ case gfx::ColorSpace2::DISPLAY_P3:
+ MOZ_CRASH("Expected BT* colorspace");
+ case gfx::ColorSpace2::BT601_525:
+ return gfx::YUVColorSpace::BT601;
+ case gfx::ColorSpace2::BT709:
+ return gfx::YUVColorSpace::BT709;
+ case gfx::ColorSpace2::BT2020:
+ return gfx::YUVColorSpace::BT2020;
+ }
+ MOZ_ASSERT_UNREACHABLE();
+ }();
+
+ const bool yFlip = destOrigin != srcOrigin;
+ const DrawBlitProg::BaseArgs baseArgs = {SubRectMat3(clipRect, ySize), yFlip,
+ destSize, Nothing()};
+ const DrawBlitProg::YUVArgs yuvArgs = {
+ SubRectMat3(clipRect, uvSize, divisors), Some(yuvColorSpace)};
+
+ const auto& prog = GetDrawBlitProg(
+ {kFragHeader_TexExt, {kFragSample_TwoPlane, kFragConvert_ColorMatrix}});
+ prog->Draw(baseArgs, &yuvArgs);
+ return true;
+}
+
+bool GLBlitHelper::BlitDescriptor(
+ const layers::SurfaceDescriptorDXGIYCbCr& desc,
+ const gfx::IntSize& destSize, const OriginPos destOrigin) const {
+ const auto& clipSize = desc.size();
+ const auto& ySize = desc.sizeY();
+ const auto& uvSize = desc.sizeCbCr();
+ const auto& colorSpace = desc.yUVColorSpace();
+
+ const gfx::IntRect clipRect(0, 0, clipSize.width, clipSize.height);
+
+ auto handleY = desc.handleY() ? desc.handleY()->GetHandle() : nullptr;
+ auto handleCb = desc.handleCb() ? desc.handleCb()->GetHandle() : nullptr;
+ auto handleCr = desc.handleCr() ? desc.handleCr()->GetHandle() : nullptr;
+
+ const WindowsHandle handles[3] = {
+ (WindowsHandle)handleY, (WindowsHandle)handleCb, (WindowsHandle)handleCr};
+ return BlitAngleYCbCr(handles, clipRect, ySize, uvSize, colorSpace, destSize,
+ destOrigin);
+}
+
+// --
+
+bool GLBlitHelper::BlitAngleYCbCr(const WindowsHandle (&handleList)[3],
+ const gfx::IntRect& clipRect,
+ const gfx::IntSize& ySize,
+ const gfx::IntSize& uvSize,
+ const gfx::YUVColorSpace colorSpace,
+ const gfx::IntSize& destSize,
+ const OriginPos destOrigin) const {
+ const auto& d3d = GetD3D11();
+ if (!d3d) return false;
+
+ const auto srcOrigin = OriginPos::BottomLeft;
+
+ gfx::IntSize divisors;
+ if (!GuessDivisors(ySize, uvSize, &divisors)) return false;
+
+ const RefPtr<ID3D11Texture2D> texList[3] = {
+ OpenSharedTexture(d3d, handleList[0]),
+ OpenSharedTexture(d3d, handleList[1]),
+ OpenSharedTexture(d3d, handleList[2])};
+ const BindAnglePlanes bindPlanes(this, 3, texList);
+
+ const bool yFlip = destOrigin != srcOrigin;
+ const DrawBlitProg::BaseArgs baseArgs = {SubRectMat3(clipRect, ySize), yFlip,
+ destSize, Nothing()};
+ const DrawBlitProg::YUVArgs yuvArgs = {
+ SubRectMat3(clipRect, uvSize, divisors), Some(colorSpace)};
+
+ const auto& prog = GetDrawBlitProg(
+ {kFragHeader_TexExt, {kFragSample_ThreePlane, kFragConvert_ColorMatrix}});
+ prog->Draw(baseArgs, &yuvArgs);
+ return true;
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLConsts.h b/gfx/gl/GLConsts.h
new file mode 100644
index 0000000000..97744d4215
--- /dev/null
+++ b/gfx/gl/GLConsts.h
@@ -0,0 +1,7204 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// clang-format off
+
+#ifndef GLCONSTS_H_
+#define GLCONSTS_H_
+
+/**
+ * GENERATED FILE, DO NOT MODIFY DIRECTLY.
+ * This is a file generated directly from the official OpenGL registry
+ * xml available http://www.opengl.org/registry/#specfiles.
+ *
+ * To generate this file, see tutorial in 'GLConsts.py'.
+ */
+
+// GL
+#define LOCAL_GL_1PASS_EXT 0x80A1
+#define LOCAL_GL_1PASS_SGIS 0x80A1
+#define LOCAL_GL_2D 0x0600
+#define LOCAL_GL_2PASS_0_EXT 0x80A2
+#define LOCAL_GL_2PASS_0_SGIS 0x80A2
+#define LOCAL_GL_2PASS_1_EXT 0x80A3
+#define LOCAL_GL_2PASS_1_SGIS 0x80A3
+#define LOCAL_GL_2X_BIT_ATI 0x00000001
+#define LOCAL_GL_2_BYTES 0x1407
+#define LOCAL_GL_2_BYTES_NV 0x1407
+#define LOCAL_GL_3D 0x0601
+#define LOCAL_GL_3DC_XY_AMD 0x87FA
+#define LOCAL_GL_3DC_X_AMD 0x87F9
+#define LOCAL_GL_3D_COLOR 0x0602
+#define LOCAL_GL_3D_COLOR_TEXTURE 0x0603
+#define LOCAL_GL_3_BYTES 0x1408
+#define LOCAL_GL_3_BYTES_NV 0x1408
+#define LOCAL_GL_422_AVERAGE_EXT 0x80CE
+#define LOCAL_GL_422_EXT 0x80CC
+#define LOCAL_GL_422_REV_AVERAGE_EXT 0x80CF
+#define LOCAL_GL_422_REV_EXT 0x80CD
+#define LOCAL_GL_4D_COLOR_TEXTURE 0x0604
+#define LOCAL_GL_4PASS_0_EXT 0x80A4
+#define LOCAL_GL_4PASS_0_SGIS 0x80A4
+#define LOCAL_GL_4PASS_1_EXT 0x80A5
+#define LOCAL_GL_4PASS_1_SGIS 0x80A5
+#define LOCAL_GL_4PASS_2_EXT 0x80A6
+#define LOCAL_GL_4PASS_2_SGIS 0x80A6
+#define LOCAL_GL_4PASS_3_EXT 0x80A7
+#define LOCAL_GL_4PASS_3_SGIS 0x80A7
+#define LOCAL_GL_4X_BIT_ATI 0x00000002
+#define LOCAL_GL_4_BYTES 0x1409
+#define LOCAL_GL_4_BYTES_NV 0x1409
+#define LOCAL_GL_8X_BIT_ATI 0x00000004
+#define LOCAL_GL_ABGR_EXT 0x8000
+#define LOCAL_GL_ACCUM 0x0100
+#define LOCAL_GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD
+#define LOCAL_GL_ACCUM_ALPHA_BITS 0x0D5B
+#define LOCAL_GL_ACCUM_BLUE_BITS 0x0D5A
+#define LOCAL_GL_ACCUM_BUFFER_BIT 0x00000200
+#define LOCAL_GL_ACCUM_CLEAR_VALUE 0x0B80
+#define LOCAL_GL_ACCUM_GREEN_BITS 0x0D59
+#define LOCAL_GL_ACCUM_RED_BITS 0x0D58
+#define LOCAL_GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define LOCAL_GL_ACTIVE_ATTRIBUTES 0x8B89
+#define LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define LOCAL_GL_ACTIVE_PROGRAM 0x8259
+#define LOCAL_GL_ACTIVE_PROGRAM_EXT 0x8B8D
+#define LOCAL_GL_ACTIVE_RESOURCES 0x92F5
+#define LOCAL_GL_ACTIVE_STENCIL_FACE_EXT 0x8911
+#define LOCAL_GL_ACTIVE_SUBROUTINES 0x8DE5
+#define LOCAL_GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define LOCAL_GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define LOCAL_GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define LOCAL_GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define LOCAL_GL_ACTIVE_TEXTURE 0x84E0
+#define LOCAL_GL_ACTIVE_TEXTURE_ARB 0x84E0
+#define LOCAL_GL_ACTIVE_UNIFORMS 0x8B86
+#define LOCAL_GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define LOCAL_GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define LOCAL_GL_ACTIVE_VARIABLES 0x9305
+#define LOCAL_GL_ACTIVE_VARYINGS_NV 0x8C81
+#define LOCAL_GL_ACTIVE_VARYING_MAX_LENGTH_NV 0x8C82
+#define LOCAL_GL_ACTIVE_VERTEX_UNITS_ARB 0x86A5
+#define LOCAL_GL_ADD 0x0104
+#define LOCAL_GL_ADD_ATI 0x8963
+#define LOCAL_GL_ADD_BLEND_IMG 0x8C09
+#define LOCAL_GL_ADD_SIGNED 0x8574
+#define LOCAL_GL_ADD_SIGNED_ARB 0x8574
+#define LOCAL_GL_ADD_SIGNED_EXT 0x8574
+#define LOCAL_GL_ADJACENT_PAIRS_NV 0x90AE
+#define LOCAL_GL_AFFINE_2D_NV 0x9092
+#define LOCAL_GL_AFFINE_3D_NV 0x9094
+#define LOCAL_GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define LOCAL_GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define LOCAL_GL_ALLOW_DRAW_FRG_HINT_PGI 0x1A210
+#define LOCAL_GL_ALLOW_DRAW_MEM_HINT_PGI 0x1A211
+#define LOCAL_GL_ALLOW_DRAW_OBJ_HINT_PGI 0x1A20E
+#define LOCAL_GL_ALLOW_DRAW_WIN_HINT_PGI 0x1A20F
+#define LOCAL_GL_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define LOCAL_GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define LOCAL_GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF
+#define LOCAL_GL_ALL_COMPLETED_NV 0x84F2
+#define LOCAL_GL_ALL_PIXELS_AMD 0xFFFFFFFF
+#define LOCAL_GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define LOCAL_GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF
+#define LOCAL_GL_ALL_STATIC_DATA_IBM 103060
+#define LOCAL_GL_ALPHA 0x1906
+#define LOCAL_GL_ALPHA12 0x803D
+#define LOCAL_GL_ALPHA12_EXT 0x803D
+#define LOCAL_GL_ALPHA16 0x803E
+#define LOCAL_GL_ALPHA16F_ARB 0x881C
+#define LOCAL_GL_ALPHA16F_EXT 0x881C
+#define LOCAL_GL_ALPHA16I_EXT 0x8D8A
+#define LOCAL_GL_ALPHA16UI_EXT 0x8D78
+#define LOCAL_GL_ALPHA16_EXT 0x803E
+#define LOCAL_GL_ALPHA16_SNORM 0x9018
+#define LOCAL_GL_ALPHA32F_ARB 0x8816
+#define LOCAL_GL_ALPHA32F_EXT 0x8816
+#define LOCAL_GL_ALPHA32I_EXT 0x8D84
+#define LOCAL_GL_ALPHA32UI_EXT 0x8D72
+#define LOCAL_GL_ALPHA4 0x803B
+#define LOCAL_GL_ALPHA4_EXT 0x803B
+#define LOCAL_GL_ALPHA8 0x803C
+#define LOCAL_GL_ALPHA8I_EXT 0x8D90
+#define LOCAL_GL_ALPHA8UI_EXT 0x8D7E
+#define LOCAL_GL_ALPHA8_EXT 0x803C
+#define LOCAL_GL_ALPHA8_OES 0x803C
+#define LOCAL_GL_ALPHA8_SNORM 0x9014
+#define LOCAL_GL_ALPHA_BIAS 0x0D1D
+#define LOCAL_GL_ALPHA_BITS 0x0D55
+#define LOCAL_GL_ALPHA_FLOAT16_APPLE 0x881C
+#define LOCAL_GL_ALPHA_FLOAT16_ATI 0x881C
+#define LOCAL_GL_ALPHA_FLOAT32_APPLE 0x8816
+#define LOCAL_GL_ALPHA_FLOAT32_ATI 0x8816
+#define LOCAL_GL_ALPHA_INTEGER 0x8D97
+#define LOCAL_GL_ALPHA_INTEGER_EXT 0x8D97
+#define LOCAL_GL_ALPHA_MAX_CLAMP_INGR 0x8567
+#define LOCAL_GL_ALPHA_MAX_SGIX 0x8321
+#define LOCAL_GL_ALPHA_MIN_CLAMP_INGR 0x8563
+#define LOCAL_GL_ALPHA_MIN_SGIX 0x8320
+#define LOCAL_GL_ALPHA_REF_COMMAND_NV 0x000F
+#define LOCAL_GL_ALPHA_SCALE 0x0D1C
+#define LOCAL_GL_ALPHA_SNORM 0x9010
+#define LOCAL_GL_ALPHA_TEST 0x0BC0
+#define LOCAL_GL_ALPHA_TEST_FUNC 0x0BC1
+#define LOCAL_GL_ALPHA_TEST_FUNC_QCOM 0x0BC1
+#define LOCAL_GL_ALPHA_TEST_QCOM 0x0BC0
+#define LOCAL_GL_ALPHA_TEST_REF 0x0BC2
+#define LOCAL_GL_ALPHA_TEST_REF_QCOM 0x0BC2
+#define LOCAL_GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV 0x934D
+#define LOCAL_GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV 0x934F
+#define LOCAL_GL_ALPHA_TO_COVERAGE_DITHER_ENABLE_NV 0x934E
+#define LOCAL_GL_ALPHA_TO_COVERAGE_DITHER_MODE_NV 0x92BF
+#define LOCAL_GL_ALREADY_SIGNALED 0x911A
+#define LOCAL_GL_ALREADY_SIGNALED_APPLE 0x911A
+#define LOCAL_GL_ALWAYS 0x0207
+#define LOCAL_GL_ALWAYS_FAST_HINT_PGI 0x1A20C
+#define LOCAL_GL_ALWAYS_SOFT_HINT_PGI 0x1A20D
+#define LOCAL_GL_AMBIENT 0x1200
+#define LOCAL_GL_AMBIENT_AND_DIFFUSE 0x1602
+#define LOCAL_GL_AND 0x1501
+#define LOCAL_GL_AND_INVERTED 0x1504
+#define LOCAL_GL_AND_REVERSE 0x1502
+#define LOCAL_GL_ANY_SAMPLES_PASSED 0x8C2F
+#define LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define LOCAL_GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
+#define LOCAL_GL_ANY_SAMPLES_PASSED_EXT 0x8C2F
+#define LOCAL_GL_ARC_TO_NV 0xFE
+#define LOCAL_GL_ARRAY_BUFFER 0x8892
+#define LOCAL_GL_ARRAY_BUFFER_ARB 0x8892
+#define LOCAL_GL_ARRAY_BUFFER_BINDING 0x8894
+#define LOCAL_GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define LOCAL_GL_ARRAY_ELEMENT_LOCK_COUNT_EXT 0x81A9
+#define LOCAL_GL_ARRAY_ELEMENT_LOCK_FIRST_EXT 0x81A8
+#define LOCAL_GL_ARRAY_OBJECT_BUFFER_ATI 0x8766
+#define LOCAL_GL_ARRAY_OBJECT_OFFSET_ATI 0x8767
+#define LOCAL_GL_ARRAY_SIZE 0x92FB
+#define LOCAL_GL_ARRAY_STRIDE 0x92FE
+#define LOCAL_GL_ASYNC_DRAW_PIXELS_SGIX 0x835D
+#define LOCAL_GL_ASYNC_HISTOGRAM_SGIX 0x832C
+#define LOCAL_GL_ASYNC_MARKER_SGIX 0x8329
+#define LOCAL_GL_ASYNC_READ_PIXELS_SGIX 0x835E
+#define LOCAL_GL_ASYNC_TEX_IMAGE_SGIX 0x835C
+#define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93
+#define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE
+#define LOCAL_GL_ATC_RGB_AMD 0x8C92
+#define LOCAL_GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define LOCAL_GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV 0x959E
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV 0x959F
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define LOCAL_GL_ATTACHED_MEMORY_OBJECT_NV 0x95A4
+#define LOCAL_GL_ATTACHED_MEMORY_OFFSET_NV 0x95A5
+#define LOCAL_GL_ATTACHED_SHADERS 0x8B85
+#define LOCAL_GL_ATTENUATION_EXT 0x834D
+#define LOCAL_GL_ATTRIBUTE_ADDRESS_COMMAND_NV 0x0009
+#define LOCAL_GL_ATTRIB_ARRAY_POINTER_NV 0x8645
+#define LOCAL_GL_ATTRIB_ARRAY_SIZE_NV 0x8623
+#define LOCAL_GL_ATTRIB_ARRAY_STRIDE_NV 0x8624
+#define LOCAL_GL_ATTRIB_ARRAY_TYPE_NV 0x8625
+#define LOCAL_GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define LOCAL_GL_AUTO_GENERATE_MIPMAP 0x8295
+#define LOCAL_GL_AUTO_NORMAL 0x0D80
+#define LOCAL_GL_AUX0 0x0409
+#define LOCAL_GL_AUX1 0x040A
+#define LOCAL_GL_AUX2 0x040B
+#define LOCAL_GL_AUX3 0x040C
+#define LOCAL_GL_AUX_BUFFERS 0x0C00
+#define LOCAL_GL_AUX_DEPTH_STENCIL_APPLE 0x8A14
+#define LOCAL_GL_AVERAGE_EXT 0x8335
+#define LOCAL_GL_AVERAGE_HP 0x8160
+#define LOCAL_GL_BACK 0x0405
+#define LOCAL_GL_BACK_LEFT 0x0402
+#define LOCAL_GL_BACK_NORMALS_HINT_PGI 0x1A223
+#define LOCAL_GL_BACK_PRIMARY_COLOR_NV 0x8C77
+#define LOCAL_GL_BACK_RIGHT 0x0403
+#define LOCAL_GL_BACK_SECONDARY_COLOR_NV 0x8C78
+#define LOCAL_GL_BEVEL_NV 0x90A6
+#define LOCAL_GL_BGR 0x80E0
+#define LOCAL_GL_BGRA 0x80E1
+#define LOCAL_GL_BGRA8_EXT 0x93A1
+#define LOCAL_GL_BGRA_EXT 0x80E1
+#define LOCAL_GL_BGRA_IMG 0x80E1
+#define LOCAL_GL_BGRA_INTEGER 0x8D9B
+#define LOCAL_GL_BGRA_INTEGER_EXT 0x8D9B
+#define LOCAL_GL_BGR_EXT 0x80E0
+#define LOCAL_GL_BGR_INTEGER 0x8D9A
+#define LOCAL_GL_BGR_INTEGER_EXT 0x8D9A
+#define LOCAL_GL_BIAS_BIT_ATI 0x00000008
+#define LOCAL_GL_BIAS_BY_NEGATIVE_ONE_HALF_NV 0x8541
+#define LOCAL_GL_BINNING_CONTROL_HINT_QCOM 0x8FB0
+#define LOCAL_GL_BINORMAL_ARRAY_EXT 0x843A
+#define LOCAL_GL_BINORMAL_ARRAY_POINTER_EXT 0x8443
+#define LOCAL_GL_BINORMAL_ARRAY_STRIDE_EXT 0x8441
+#define LOCAL_GL_BINORMAL_ARRAY_TYPE_EXT 0x8440
+#define LOCAL_GL_BITMAP 0x1A00
+#define LOCAL_GL_BITMAP_TOKEN 0x0704
+#define LOCAL_GL_BLACKHOLE_RENDER_INTEL 0x83FC
+#define LOCAL_GL_BLEND 0x0BE2
+#define LOCAL_GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#define LOCAL_GL_BLEND_ADVANCED_COHERENT_NV 0x9285
+#define LOCAL_GL_BLEND_COLOR 0x8005
+#define LOCAL_GL_BLEND_COLOR_COMMAND_NV 0x000B
+#define LOCAL_GL_BLEND_COLOR_EXT 0x8005
+#define LOCAL_GL_BLEND_DST 0x0BE0
+#define LOCAL_GL_BLEND_DST_ALPHA 0x80CA
+#define LOCAL_GL_BLEND_DST_ALPHA_EXT 0x80CA
+#define LOCAL_GL_BLEND_DST_ALPHA_OES 0x80CA
+#define LOCAL_GL_BLEND_DST_RGB 0x80C8
+#define LOCAL_GL_BLEND_DST_RGB_EXT 0x80C8
+#define LOCAL_GL_BLEND_DST_RGB_OES 0x80C8
+#define LOCAL_GL_BLEND_EQUATION 0x8009
+#define LOCAL_GL_BLEND_EQUATION_ALPHA 0x883D
+#define LOCAL_GL_BLEND_EQUATION_ALPHA_EXT 0x883D
+#define LOCAL_GL_BLEND_EQUATION_ALPHA_OES 0x883D
+#define LOCAL_GL_BLEND_EQUATION_EXT 0x8009
+#define LOCAL_GL_BLEND_EQUATION_OES 0x8009
+#define LOCAL_GL_BLEND_EQUATION_RGB 0x8009
+#define LOCAL_GL_BLEND_EQUATION_RGB_EXT 0x8009
+#define LOCAL_GL_BLEND_EQUATION_RGB_OES 0x8009
+#define LOCAL_GL_BLEND_OVERLAP_NV 0x9281
+#define LOCAL_GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280
+#define LOCAL_GL_BLEND_SRC 0x0BE1
+#define LOCAL_GL_BLEND_SRC_ALPHA 0x80CB
+#define LOCAL_GL_BLEND_SRC_ALPHA_EXT 0x80CB
+#define LOCAL_GL_BLEND_SRC_ALPHA_OES 0x80CB
+#define LOCAL_GL_BLEND_SRC_RGB 0x80C9
+#define LOCAL_GL_BLEND_SRC_RGB_EXT 0x80C9
+#define LOCAL_GL_BLEND_SRC_RGB_OES 0x80C9
+#define LOCAL_GL_BLOCK_INDEX 0x92FD
+#define LOCAL_GL_BLUE 0x1905
+#define LOCAL_GL_BLUE_BIAS 0x0D1B
+#define LOCAL_GL_BLUE_BITS 0x0D54
+#define LOCAL_GL_BLUE_BIT_ATI 0x00000004
+#define LOCAL_GL_BLUE_INTEGER 0x8D96
+#define LOCAL_GL_BLUE_INTEGER_EXT 0x8D96
+#define LOCAL_GL_BLUE_MAX_CLAMP_INGR 0x8566
+#define LOCAL_GL_BLUE_MIN_CLAMP_INGR 0x8562
+#define LOCAL_GL_BLUE_NV 0x1905
+#define LOCAL_GL_BLUE_SCALE 0x0D1A
+#define LOCAL_GL_BOLD_BIT_NV 0x01
+#define LOCAL_GL_BOOL 0x8B56
+#define LOCAL_GL_BOOL_ARB 0x8B56
+#define LOCAL_GL_BOOL_VEC2 0x8B57
+#define LOCAL_GL_BOOL_VEC2_ARB 0x8B57
+#define LOCAL_GL_BOOL_VEC3 0x8B58
+#define LOCAL_GL_BOOL_VEC3_ARB 0x8B58
+#define LOCAL_GL_BOOL_VEC4 0x8B59
+#define LOCAL_GL_BOOL_VEC4_ARB 0x8B59
+#define LOCAL_GL_BOUNDING_BOX_NV 0x908D
+#define LOCAL_GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define LOCAL_GL_BROWSER_DEFAULT_WEBGL 0x9244
+#define LOCAL_GL_BUFFER 0x82E0
+#define LOCAL_GL_BUFFER_ACCESS 0x88BB
+#define LOCAL_GL_BUFFER_ACCESS_ARB 0x88BB
+#define LOCAL_GL_BUFFER_ACCESS_FLAGS 0x911F
+#define LOCAL_GL_BUFFER_ACCESS_OES 0x88BB
+#define LOCAL_GL_BUFFER_BINDING 0x9302
+#define LOCAL_GL_BUFFER_DATA_SIZE 0x9303
+#define LOCAL_GL_BUFFER_FLUSHING_UNMAP_APPLE 0x8A13
+#define LOCAL_GL_BUFFER_GPU_ADDRESS_NV 0x8F1D
+#define LOCAL_GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define LOCAL_GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
+#define LOCAL_GL_BUFFER_KHR 0x82E0
+#define LOCAL_GL_BUFFER_MAPPED 0x88BC
+#define LOCAL_GL_BUFFER_MAPPED_ARB 0x88BC
+#define LOCAL_GL_BUFFER_MAPPED_OES 0x88BC
+#define LOCAL_GL_BUFFER_MAP_LENGTH 0x9120
+#define LOCAL_GL_BUFFER_MAP_OFFSET 0x9121
+#define LOCAL_GL_BUFFER_MAP_POINTER 0x88BD
+#define LOCAL_GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define LOCAL_GL_BUFFER_MAP_POINTER_OES 0x88BD
+#define LOCAL_GL_BUFFER_OBJECT_APPLE 0x85B3
+#define LOCAL_GL_BUFFER_OBJECT_EXT 0x9151
+#define LOCAL_GL_BUFFER_SERIALIZED_MODIFY_APPLE 0x8A12
+#define LOCAL_GL_BUFFER_SIZE 0x8764
+#define LOCAL_GL_BUFFER_SIZE_ARB 0x8764
+#define LOCAL_GL_BUFFER_STORAGE_FLAGS 0x8220
+#define LOCAL_GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
+#define LOCAL_GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define LOCAL_GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200
+#define LOCAL_GL_BUFFER_USAGE 0x8765
+#define LOCAL_GL_BUFFER_USAGE_ARB 0x8765
+#define LOCAL_GL_BUFFER_VARIABLE 0x92E5
+#define LOCAL_GL_BUMP_ENVMAP_ATI 0x877B
+#define LOCAL_GL_BUMP_NUM_TEX_UNITS_ATI 0x8777
+#define LOCAL_GL_BUMP_ROT_MATRIX_ATI 0x8775
+#define LOCAL_GL_BUMP_ROT_MATRIX_SIZE_ATI 0x8776
+#define LOCAL_GL_BUMP_TARGET_ATI 0x877C
+#define LOCAL_GL_BUMP_TEX_UNITS_ATI 0x8778
+#define LOCAL_GL_BYTE 0x1400
+#define LOCAL_GL_C3F_V3F 0x2A24
+#define LOCAL_GL_C4F_N3F_V3F 0x2A26
+#define LOCAL_GL_C4UB_V2F 0x2A22
+#define LOCAL_GL_C4UB_V3F 0x2A23
+#define LOCAL_GL_CALLIGRAPHIC_FRAGMENT_SGIX 0x8183
+#define LOCAL_GL_CAVEAT_SUPPORT 0x82B8
+#define LOCAL_GL_CCW 0x0901
+#define LOCAL_GL_CIRCULAR_CCW_ARC_TO_NV 0xF8
+#define LOCAL_GL_CIRCULAR_CW_ARC_TO_NV 0xFA
+#define LOCAL_GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC
+#define LOCAL_GL_CLAMP 0x2900
+#define LOCAL_GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define LOCAL_GL_CLAMP_FRAGMENT_COLOR_ARB 0x891B
+#define LOCAL_GL_CLAMP_READ_COLOR 0x891C
+#define LOCAL_GL_CLAMP_READ_COLOR_ARB 0x891C
+#define LOCAL_GL_CLAMP_TO_BORDER 0x812D
+#define LOCAL_GL_CLAMP_TO_BORDER_ARB 0x812D
+#define LOCAL_GL_CLAMP_TO_BORDER_EXT 0x812D
+#define LOCAL_GL_CLAMP_TO_BORDER_NV 0x812D
+#define LOCAL_GL_CLAMP_TO_BORDER_OES 0x812D
+#define LOCAL_GL_CLAMP_TO_BORDER_SGIS 0x812D
+#define LOCAL_GL_CLAMP_TO_EDGE 0x812F
+#define LOCAL_GL_CLAMP_TO_EDGE_SGIS 0x812F
+#define LOCAL_GL_CLAMP_VERTEX_COLOR 0x891A
+#define LOCAL_GL_CLAMP_VERTEX_COLOR_ARB 0x891A
+#define LOCAL_GL_CLEAR 0x1500
+#define LOCAL_GL_CLEAR_BUFFER 0x82B4
+#define LOCAL_GL_CLEAR_TEXTURE 0x9365
+#define LOCAL_GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define LOCAL_GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
+#define LOCAL_GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define LOCAL_GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define LOCAL_GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define LOCAL_GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define LOCAL_GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define LOCAL_GL_CLIENT_STORAGE_BIT 0x0200
+#define LOCAL_GL_CLIENT_STORAGE_BIT_EXT 0x0200
+#define LOCAL_GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define LOCAL_GL_CLIPPING_INPUT_PRIMITIVES 0x82F6
+#define LOCAL_GL_CLIPPING_INPUT_PRIMITIVES_ARB 0x82F6
+#define LOCAL_GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7
+#define LOCAL_GL_CLIPPING_OUTPUT_PRIMITIVES_ARB 0x82F7
+#define LOCAL_GL_CLIP_DEPTH_MODE 0x935D
+#define LOCAL_GL_CLIP_DEPTH_MODE_EXT 0x935D
+#define LOCAL_GL_CLIP_DISTANCE0 0x3000
+#define LOCAL_GL_CLIP_DISTANCE0_APPLE 0x3000
+#define LOCAL_GL_CLIP_DISTANCE0_EXT 0x3000
+#define LOCAL_GL_CLIP_DISTANCE1 0x3001
+#define LOCAL_GL_CLIP_DISTANCE1_APPLE 0x3001
+#define LOCAL_GL_CLIP_DISTANCE1_EXT 0x3001
+#define LOCAL_GL_CLIP_DISTANCE2 0x3002
+#define LOCAL_GL_CLIP_DISTANCE2_APPLE 0x3002
+#define LOCAL_GL_CLIP_DISTANCE2_EXT 0x3002
+#define LOCAL_GL_CLIP_DISTANCE3 0x3003
+#define LOCAL_GL_CLIP_DISTANCE3_APPLE 0x3003
+#define LOCAL_GL_CLIP_DISTANCE3_EXT 0x3003
+#define LOCAL_GL_CLIP_DISTANCE4 0x3004
+#define LOCAL_GL_CLIP_DISTANCE4_APPLE 0x3004
+#define LOCAL_GL_CLIP_DISTANCE4_EXT 0x3004
+#define LOCAL_GL_CLIP_DISTANCE5 0x3005
+#define LOCAL_GL_CLIP_DISTANCE5_APPLE 0x3005
+#define LOCAL_GL_CLIP_DISTANCE5_EXT 0x3005
+#define LOCAL_GL_CLIP_DISTANCE6 0x3006
+#define LOCAL_GL_CLIP_DISTANCE6_APPLE 0x3006
+#define LOCAL_GL_CLIP_DISTANCE6_EXT 0x3006
+#define LOCAL_GL_CLIP_DISTANCE7 0x3007
+#define LOCAL_GL_CLIP_DISTANCE7_APPLE 0x3007
+#define LOCAL_GL_CLIP_DISTANCE7_EXT 0x3007
+#define LOCAL_GL_CLIP_DISTANCE_NV 0x8C7A
+#define LOCAL_GL_CLIP_FAR_HINT_PGI 0x1A221
+#define LOCAL_GL_CLIP_NEAR_HINT_PGI 0x1A220
+#define LOCAL_GL_CLIP_ORIGIN 0x935C
+#define LOCAL_GL_CLIP_ORIGIN_EXT 0x935C
+#define LOCAL_GL_CLIP_PLANE0 0x3000
+#define LOCAL_GL_CLIP_PLANE0_IMG 0x3000
+#define LOCAL_GL_CLIP_PLANE1 0x3001
+#define LOCAL_GL_CLIP_PLANE1_IMG 0x3001
+#define LOCAL_GL_CLIP_PLANE2 0x3002
+#define LOCAL_GL_CLIP_PLANE2_IMG 0x3002
+#define LOCAL_GL_CLIP_PLANE3 0x3003
+#define LOCAL_GL_CLIP_PLANE3_IMG 0x3003
+#define LOCAL_GL_CLIP_PLANE4 0x3004
+#define LOCAL_GL_CLIP_PLANE4_IMG 0x3004
+#define LOCAL_GL_CLIP_PLANE5 0x3005
+#define LOCAL_GL_CLIP_PLANE5_IMG 0x3005
+#define LOCAL_GL_CLIP_VOLUME_CLIPPING_HINT_EXT 0x80F0
+#define LOCAL_GL_CLOSE_PATH_NV 0x00
+#define LOCAL_GL_CMYKA_EXT 0x800D
+#define LOCAL_GL_CMYK_EXT 0x800C
+#define LOCAL_GL_CND0_ATI 0x896B
+#define LOCAL_GL_CND_ATI 0x896A
+#define LOCAL_GL_COEFF 0x0A00
+#define LOCAL_GL_COLOR 0x1800
+#define LOCAL_GL_COLOR3_BIT_PGI 0x00010000
+#define LOCAL_GL_COLOR4_BIT_PGI 0x00020000
+#define LOCAL_GL_COLORBURN 0x929A
+#define LOCAL_GL_COLORBURN_KHR 0x929A
+#define LOCAL_GL_COLORBURN_NV 0x929A
+#define LOCAL_GL_COLORDODGE 0x9299
+#define LOCAL_GL_COLORDODGE_KHR 0x9299
+#define LOCAL_GL_COLORDODGE_NV 0x9299
+#define LOCAL_GL_COLOR_ALPHA_PAIRING_ATI 0x8975
+#define LOCAL_GL_COLOR_ARRAY 0x8076
+#define LOCAL_GL_COLOR_ARRAY_ADDRESS_NV 0x8F23
+#define LOCAL_GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define LOCAL_GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define LOCAL_GL_COLOR_ARRAY_COUNT_EXT 0x8084
+#define LOCAL_GL_COLOR_ARRAY_EXT 0x8076
+#define LOCAL_GL_COLOR_ARRAY_LENGTH_NV 0x8F2D
+#define LOCAL_GL_COLOR_ARRAY_LIST_IBM 103072
+#define LOCAL_GL_COLOR_ARRAY_LIST_STRIDE_IBM 103082
+#define LOCAL_GL_COLOR_ARRAY_PARALLEL_POINTERS_INTEL 0x83F7
+#define LOCAL_GL_COLOR_ARRAY_POINTER 0x8090
+#define LOCAL_GL_COLOR_ARRAY_POINTER_EXT 0x8090
+#define LOCAL_GL_COLOR_ARRAY_SIZE 0x8081
+#define LOCAL_GL_COLOR_ARRAY_SIZE_EXT 0x8081
+#define LOCAL_GL_COLOR_ARRAY_STRIDE 0x8083
+#define LOCAL_GL_COLOR_ARRAY_STRIDE_EXT 0x8083
+#define LOCAL_GL_COLOR_ARRAY_TYPE 0x8082
+#define LOCAL_GL_COLOR_ARRAY_TYPE_EXT 0x8082
+#define LOCAL_GL_COLOR_ATTACHMENT0 0x8CE0
+#define LOCAL_GL_COLOR_ATTACHMENT0_EXT 0x8CE0
+#define LOCAL_GL_COLOR_ATTACHMENT0_NV 0x8CE0
+#define LOCAL_GL_COLOR_ATTACHMENT0_OES 0x8CE0
+#define LOCAL_GL_COLOR_ATTACHMENT1 0x8CE1
+#define LOCAL_GL_COLOR_ATTACHMENT10 0x8CEA
+#define LOCAL_GL_COLOR_ATTACHMENT10_EXT 0x8CEA
+#define LOCAL_GL_COLOR_ATTACHMENT10_NV 0x8CEA
+#define LOCAL_GL_COLOR_ATTACHMENT11 0x8CEB
+#define LOCAL_GL_COLOR_ATTACHMENT11_EXT 0x8CEB
+#define LOCAL_GL_COLOR_ATTACHMENT11_NV 0x8CEB
+#define LOCAL_GL_COLOR_ATTACHMENT12 0x8CEC
+#define LOCAL_GL_COLOR_ATTACHMENT12_EXT 0x8CEC
+#define LOCAL_GL_COLOR_ATTACHMENT12_NV 0x8CEC
+#define LOCAL_GL_COLOR_ATTACHMENT13 0x8CED
+#define LOCAL_GL_COLOR_ATTACHMENT13_EXT 0x8CED
+#define LOCAL_GL_COLOR_ATTACHMENT13_NV 0x8CED
+#define LOCAL_GL_COLOR_ATTACHMENT14 0x8CEE
+#define LOCAL_GL_COLOR_ATTACHMENT14_EXT 0x8CEE
+#define LOCAL_GL_COLOR_ATTACHMENT14_NV 0x8CEE
+#define LOCAL_GL_COLOR_ATTACHMENT15 0x8CEF
+#define LOCAL_GL_COLOR_ATTACHMENT15_EXT 0x8CEF
+#define LOCAL_GL_COLOR_ATTACHMENT15_NV 0x8CEF
+#define LOCAL_GL_COLOR_ATTACHMENT16 0x8CF0
+#define LOCAL_GL_COLOR_ATTACHMENT17 0x8CF1
+#define LOCAL_GL_COLOR_ATTACHMENT18 0x8CF2
+#define LOCAL_GL_COLOR_ATTACHMENT19 0x8CF3
+#define LOCAL_GL_COLOR_ATTACHMENT1_EXT 0x8CE1
+#define LOCAL_GL_COLOR_ATTACHMENT1_NV 0x8CE1
+#define LOCAL_GL_COLOR_ATTACHMENT2 0x8CE2
+#define LOCAL_GL_COLOR_ATTACHMENT20 0x8CF4
+#define LOCAL_GL_COLOR_ATTACHMENT21 0x8CF5
+#define LOCAL_GL_COLOR_ATTACHMENT22 0x8CF6
+#define LOCAL_GL_COLOR_ATTACHMENT23 0x8CF7
+#define LOCAL_GL_COLOR_ATTACHMENT24 0x8CF8
+#define LOCAL_GL_COLOR_ATTACHMENT25 0x8CF9
+#define LOCAL_GL_COLOR_ATTACHMENT26 0x8CFA
+#define LOCAL_GL_COLOR_ATTACHMENT27 0x8CFB
+#define LOCAL_GL_COLOR_ATTACHMENT28 0x8CFC
+#define LOCAL_GL_COLOR_ATTACHMENT29 0x8CFD
+#define LOCAL_GL_COLOR_ATTACHMENT2_EXT 0x8CE2
+#define LOCAL_GL_COLOR_ATTACHMENT2_NV 0x8CE2
+#define LOCAL_GL_COLOR_ATTACHMENT3 0x8CE3
+#define LOCAL_GL_COLOR_ATTACHMENT30 0x8CFE
+#define LOCAL_GL_COLOR_ATTACHMENT31 0x8CFF
+#define LOCAL_GL_COLOR_ATTACHMENT3_EXT 0x8CE3
+#define LOCAL_GL_COLOR_ATTACHMENT3_NV 0x8CE3
+#define LOCAL_GL_COLOR_ATTACHMENT4 0x8CE4
+#define LOCAL_GL_COLOR_ATTACHMENT4_EXT 0x8CE4
+#define LOCAL_GL_COLOR_ATTACHMENT4_NV 0x8CE4
+#define LOCAL_GL_COLOR_ATTACHMENT5 0x8CE5
+#define LOCAL_GL_COLOR_ATTACHMENT5_EXT 0x8CE5
+#define LOCAL_GL_COLOR_ATTACHMENT5_NV 0x8CE5
+#define LOCAL_GL_COLOR_ATTACHMENT6 0x8CE6
+#define LOCAL_GL_COLOR_ATTACHMENT6_EXT 0x8CE6
+#define LOCAL_GL_COLOR_ATTACHMENT6_NV 0x8CE6
+#define LOCAL_GL_COLOR_ATTACHMENT7 0x8CE7
+#define LOCAL_GL_COLOR_ATTACHMENT7_EXT 0x8CE7
+#define LOCAL_GL_COLOR_ATTACHMENT7_NV 0x8CE7
+#define LOCAL_GL_COLOR_ATTACHMENT8 0x8CE8
+#define LOCAL_GL_COLOR_ATTACHMENT8_EXT 0x8CE8
+#define LOCAL_GL_COLOR_ATTACHMENT8_NV 0x8CE8
+#define LOCAL_GL_COLOR_ATTACHMENT9 0x8CE9
+#define LOCAL_GL_COLOR_ATTACHMENT9_EXT 0x8CE9
+#define LOCAL_GL_COLOR_ATTACHMENT9_NV 0x8CE9
+#define LOCAL_GL_COLOR_ATTACHMENT_EXT 0x90F0
+#define LOCAL_GL_COLOR_BUFFER_BIT 0x00004000
+#define LOCAL_GL_COLOR_BUFFER_BIT0_QCOM 0x00000001
+#define LOCAL_GL_COLOR_BUFFER_BIT1_QCOM 0x00000002
+#define LOCAL_GL_COLOR_BUFFER_BIT2_QCOM 0x00000004
+#define LOCAL_GL_COLOR_BUFFER_BIT3_QCOM 0x00000008
+#define LOCAL_GL_COLOR_BUFFER_BIT4_QCOM 0x00000010
+#define LOCAL_GL_COLOR_BUFFER_BIT5_QCOM 0x00000020
+#define LOCAL_GL_COLOR_BUFFER_BIT6_QCOM 0x00000040
+#define LOCAL_GL_COLOR_BUFFER_BIT7_QCOM 0x00000080
+#define LOCAL_GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI 0x8835
+#define LOCAL_GL_COLOR_CLEAR_VALUE 0x0C22
+#define LOCAL_GL_COLOR_COMPONENTS 0x8283
+#define LOCAL_GL_COLOR_ENCODING 0x8296
+#define LOCAL_GL_COLOR_EXT 0x1800
+#define LOCAL_GL_COLOR_FLOAT_APPLE 0x8A0F
+#define LOCAL_GL_COLOR_INDEX 0x1900
+#define LOCAL_GL_COLOR_INDEX12_EXT 0x80E6
+#define LOCAL_GL_COLOR_INDEX16_EXT 0x80E7
+#define LOCAL_GL_COLOR_INDEX1_EXT 0x80E2
+#define LOCAL_GL_COLOR_INDEX2_EXT 0x80E3
+#define LOCAL_GL_COLOR_INDEX4_EXT 0x80E4
+#define LOCAL_GL_COLOR_INDEX8_EXT 0x80E5
+#define LOCAL_GL_COLOR_INDEXES 0x1603
+#define LOCAL_GL_COLOR_LOGIC_OP 0x0BF2
+#define LOCAL_GL_COLOR_MATERIAL 0x0B57
+#define LOCAL_GL_COLOR_MATERIAL_FACE 0x0B55
+#define LOCAL_GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define LOCAL_GL_COLOR_MATRIX 0x80B1
+#define LOCAL_GL_COLOR_MATRIX_SGI 0x80B1
+#define LOCAL_GL_COLOR_MATRIX_STACK_DEPTH 0x80B2
+#define LOCAL_GL_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B2
+#define LOCAL_GL_COLOR_RENDERABLE 0x8286
+#define LOCAL_GL_COLOR_SAMPLES_NV 0x8E20
+#define LOCAL_GL_COLOR_SUM 0x8458
+#define LOCAL_GL_COLOR_SUM_ARB 0x8458
+#define LOCAL_GL_COLOR_SUM_CLAMP_NV 0x854F
+#define LOCAL_GL_COLOR_SUM_EXT 0x8458
+#define LOCAL_GL_COLOR_TABLE 0x80D0
+#define LOCAL_GL_COLOR_TABLE_ALPHA_SIZE 0x80DD
+#define LOCAL_GL_COLOR_TABLE_ALPHA_SIZE_SGI 0x80DD
+#define LOCAL_GL_COLOR_TABLE_BIAS 0x80D7
+#define LOCAL_GL_COLOR_TABLE_BIAS_SGI 0x80D7
+#define LOCAL_GL_COLOR_TABLE_BLUE_SIZE 0x80DC
+#define LOCAL_GL_COLOR_TABLE_BLUE_SIZE_SGI 0x80DC
+#define LOCAL_GL_COLOR_TABLE_FORMAT 0x80D8
+#define LOCAL_GL_COLOR_TABLE_FORMAT_SGI 0x80D8
+#define LOCAL_GL_COLOR_TABLE_GREEN_SIZE 0x80DB
+#define LOCAL_GL_COLOR_TABLE_GREEN_SIZE_SGI 0x80DB
+#define LOCAL_GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF
+#define LOCAL_GL_COLOR_TABLE_INTENSITY_SIZE_SGI 0x80DF
+#define LOCAL_GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE
+#define LOCAL_GL_COLOR_TABLE_LUMINANCE_SIZE_SGI 0x80DE
+#define LOCAL_GL_COLOR_TABLE_RED_SIZE 0x80DA
+#define LOCAL_GL_COLOR_TABLE_RED_SIZE_SGI 0x80DA
+#define LOCAL_GL_COLOR_TABLE_SCALE 0x80D6
+#define LOCAL_GL_COLOR_TABLE_SCALE_SGI 0x80D6
+#define LOCAL_GL_COLOR_TABLE_SGI 0x80D0
+#define LOCAL_GL_COLOR_TABLE_WIDTH 0x80D9
+#define LOCAL_GL_COLOR_TABLE_WIDTH_SGI 0x80D9
+#define LOCAL_GL_COLOR_WRITEMASK 0x0C23
+#define LOCAL_GL_COMBINE 0x8570
+#define LOCAL_GL_COMBINE4_NV 0x8503
+#define LOCAL_GL_COMBINER0_NV 0x8550
+#define LOCAL_GL_COMBINER1_NV 0x8551
+#define LOCAL_GL_COMBINER2_NV 0x8552
+#define LOCAL_GL_COMBINER3_NV 0x8553
+#define LOCAL_GL_COMBINER4_NV 0x8554
+#define LOCAL_GL_COMBINER5_NV 0x8555
+#define LOCAL_GL_COMBINER6_NV 0x8556
+#define LOCAL_GL_COMBINER7_NV 0x8557
+#define LOCAL_GL_COMBINER_AB_DOT_PRODUCT_NV 0x8545
+#define LOCAL_GL_COMBINER_AB_OUTPUT_NV 0x854A
+#define LOCAL_GL_COMBINER_BIAS_NV 0x8549
+#define LOCAL_GL_COMBINER_CD_DOT_PRODUCT_NV 0x8546
+#define LOCAL_GL_COMBINER_CD_OUTPUT_NV 0x854B
+#define LOCAL_GL_COMBINER_COMPONENT_USAGE_NV 0x8544
+#define LOCAL_GL_COMBINER_INPUT_NV 0x8542
+#define LOCAL_GL_COMBINER_MAPPING_NV 0x8543
+#define LOCAL_GL_COMBINER_MUX_SUM_NV 0x8547
+#define LOCAL_GL_COMBINER_SCALE_NV 0x8548
+#define LOCAL_GL_COMBINER_SUM_OUTPUT_NV 0x854C
+#define LOCAL_GL_COMBINE_ALPHA 0x8572
+#define LOCAL_GL_COMBINE_ALPHA_ARB 0x8572
+#define LOCAL_GL_COMBINE_ALPHA_EXT 0x8572
+#define LOCAL_GL_COMBINE_ARB 0x8570
+#define LOCAL_GL_COMBINE_EXT 0x8570
+#define LOCAL_GL_COMBINE_RGB 0x8571
+#define LOCAL_GL_COMBINE_RGB_ARB 0x8571
+#define LOCAL_GL_COMBINE_RGB_EXT 0x8571
+#define LOCAL_GL_COMMAND_BARRIER_BIT 0x00000040
+#define LOCAL_GL_COMMAND_BARRIER_BIT_EXT 0x00000040
+#define LOCAL_GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E
+#define LOCAL_GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define LOCAL_GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E
+#define LOCAL_GL_COMPARE_R_TO_TEXTURE 0x884E
+#define LOCAL_GL_COMPARE_R_TO_TEXTURE_ARB 0x884E
+#define LOCAL_GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define LOCAL_GL_COMPILE 0x1300
+#define LOCAL_GL_COMPILE_AND_EXECUTE 0x1301
+#define LOCAL_GL_COMPILE_STATUS 0x8B81
+#define LOCAL_GL_COMPLETION_STATUS_ARB 0x91B1
+#define LOCAL_GL_COMPLETION_STATUS_KHR 0x91B1
+#define LOCAL_GL_COMPRESSED_ALPHA 0x84E9
+#define LOCAL_GL_COMPRESSED_ALPHA_ARB 0x84E9
+#define LOCAL_GL_COMPRESSED_INTENSITY 0x84EC
+#define LOCAL_GL_COMPRESSED_INTENSITY_ARB 0x84EC
+#define LOCAL_GL_COMPRESSED_LUMINANCE 0x84EA
+#define LOCAL_GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define LOCAL_GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI 0x8837
+#define LOCAL_GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
+#define LOCAL_GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72
+#define LOCAL_GL_COMPRESSED_LUMINANCE_ARB 0x84EA
+#define LOCAL_GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70
+#define LOCAL_GL_COMPRESSED_R11_EAC 0x9270
+#define LOCAL_GL_COMPRESSED_R11_EAC_OES 0x9270
+#define LOCAL_GL_COMPRESSED_RED 0x8225
+#define LOCAL_GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define LOCAL_GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define LOCAL_GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define LOCAL_GL_COMPRESSED_RG 0x8226
+#define LOCAL_GL_COMPRESSED_RG11_EAC 0x9272
+#define LOCAL_GL_COMPRESSED_RG11_EAC_OES 0x9272
+#define LOCAL_GL_COMPRESSED_RGB 0x84ED
+#define LOCAL_GL_COMPRESSED_RGB8_ETC2 0x9274
+#define LOCAL_GL_COMPRESSED_RGB8_ETC2_OES 0x9274
+#define LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9276
+#define LOCAL_GL_COMPRESSED_RGBA 0x84EE
+#define LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC_OES 0x9278
+#define LOCAL_GL_COMPRESSED_RGBA_ARB 0x84EE
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7
+#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7
+#define LOCAL_GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define LOCAL_GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
+#define LOCAL_GL_COMPRESSED_RGBA_BPTC_UNORM_EXT 0x8E8C
+#define LOCAL_GL_COMPRESSED_RGBA_FXT1_3DFX 0x86B1
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
+#define LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
+#define LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2
+#define LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
+#define LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3
+#define LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define LOCAL_GL_COMPRESSED_RGB_ARB 0x84ED
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT 0x8E8E
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
+#define LOCAL_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT 0x8E8F
+#define LOCAL_GL_COMPRESSED_RGB_FXT1_3DFX 0x86B0
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
+#define LOCAL_GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define LOCAL_GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73
+#define LOCAL_GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71
+#define LOCAL_GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define LOCAL_GL_COMPRESSED_SIGNED_R11_EAC_OES 0x9271
+#define LOCAL_GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
+#define LOCAL_GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define LOCAL_GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC_OES 0x9273
+#define LOCAL_GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define LOCAL_GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define LOCAL_GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#define LOCAL_GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B
+#define LOCAL_GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A
+#define LOCAL_GL_COMPRESSED_SRGB 0x8C48
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_OES 0x9279
+#define LOCAL_GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define LOCAL_GL_COMPRESSED_SRGB8_ETC2_OES 0x9275
+#define LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9277
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT 0x8E8D
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
+#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F
+#define LOCAL_GL_COMPRESSED_SRGB_EXT 0x8C48
+#define LOCAL_GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define LOCAL_GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define LOCAL_GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
+#define LOCAL_GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C
+#define LOCAL_GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define LOCAL_GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
+#define LOCAL_GL_COMPUTE_PROGRAM_NV 0x90FB
+#define LOCAL_GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC
+#define LOCAL_GL_COMPUTE_SHADER 0x91B9
+#define LOCAL_GL_COMPUTE_SHADER_BIT 0x00000020
+#define LOCAL_GL_COMPUTE_SHADER_INVOCATIONS 0x82F5
+#define LOCAL_GL_COMPUTE_SHADER_INVOCATIONS_ARB 0x82F5
+#define LOCAL_GL_COMPUTE_SUBROUTINE 0x92ED
+#define LOCAL_GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define LOCAL_GL_COMPUTE_TEXTURE 0x82A0
+#define LOCAL_GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define LOCAL_GL_COMP_BIT_ATI 0x00000002
+#define LOCAL_GL_CONDITION_SATISFIED 0x911C
+#define LOCAL_GL_CONDITION_SATISFIED_APPLE 0x911C
+#define LOCAL_GL_CONFORMANT_NV 0x9374
+#define LOCAL_GL_CONIC_CURVE_TO_NV 0x1A
+#define LOCAL_GL_CONJOINT_NV 0x9284
+#define LOCAL_GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE
+#define LOCAL_GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
+#define LOCAL_GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B
+#define LOCAL_GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379
+#define LOCAL_GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A
+#define LOCAL_GL_CONSERVATIVE_RASTER_MODE_NV 0x954D
+#define LOCAL_GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E
+#define LOCAL_GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV 0x9550
+#define LOCAL_GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F
+#define LOCAL_GL_CONSERVE_MEMORY_HINT_PGI 0x1A1FD
+#define LOCAL_GL_CONSTANT 0x8576
+#define LOCAL_GL_CONSTANT_ALPHA 0x8003
+#define LOCAL_GL_CONSTANT_ALPHA_EXT 0x8003
+#define LOCAL_GL_CONSTANT_ARB 0x8576
+#define LOCAL_GL_CONSTANT_ATTENUATION 0x1207
+#define LOCAL_GL_CONSTANT_BORDER 0x8151
+#define LOCAL_GL_CONSTANT_BORDER_HP 0x8151
+#define LOCAL_GL_CONSTANT_COLOR 0x8001
+#define LOCAL_GL_CONSTANT_COLOR0_NV 0x852A
+#define LOCAL_GL_CONSTANT_COLOR1_NV 0x852B
+#define LOCAL_GL_CONSTANT_COLOR_EXT 0x8001
+#define LOCAL_GL_CONSTANT_EXT 0x8576
+#define LOCAL_GL_CONSTANT_NV 0x8576
+#define LOCAL_GL_CONST_EYE_NV 0x86E5
+#define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define LOCAL_GL_CONTEXT_FLAGS 0x821E
+#define LOCAL_GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define LOCAL_GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002
+#define LOCAL_GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define LOCAL_GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
+#define LOCAL_GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+#define LOCAL_GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT 0x00000010
+#define LOCAL_GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define LOCAL_GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define LOCAL_GL_CONTEXT_LOST 0x0507
+#define LOCAL_GL_CONTEXT_LOST_KHR 0x0507
+#define LOCAL_GL_CONTEXT_LOST_WEBGL 0x9242
+#define LOCAL_GL_CONTEXT_PROFILE_MASK 0x9126
+#define LOCAL_GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define LOCAL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+#define LOCAL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#define LOCAL_GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
+#define LOCAL_GL_CONTEXT_ROBUST_ACCESS 0x90F3
+#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3
+#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3
+#define LOCAL_GL_CONTINUOUS_AMD 0x9007
+#define LOCAL_GL_CONTRAST_NV 0x92A1
+#define LOCAL_GL_CONVEX_HULL_NV 0x908B
+#define LOCAL_GL_CONVOLUTION_1D 0x8010
+#define LOCAL_GL_CONVOLUTION_1D_EXT 0x8010
+#define LOCAL_GL_CONVOLUTION_2D 0x8011
+#define LOCAL_GL_CONVOLUTION_2D_EXT 0x8011
+#define LOCAL_GL_CONVOLUTION_BORDER_COLOR 0x8154
+#define LOCAL_GL_CONVOLUTION_BORDER_COLOR_HP 0x8154
+#define LOCAL_GL_CONVOLUTION_BORDER_MODE 0x8013
+#define LOCAL_GL_CONVOLUTION_BORDER_MODE_EXT 0x8013
+#define LOCAL_GL_CONVOLUTION_FILTER_BIAS 0x8015
+#define LOCAL_GL_CONVOLUTION_FILTER_BIAS_EXT 0x8015
+#define LOCAL_GL_CONVOLUTION_FILTER_SCALE 0x8014
+#define LOCAL_GL_CONVOLUTION_FILTER_SCALE_EXT 0x8014
+#define LOCAL_GL_CONVOLUTION_FORMAT 0x8017
+#define LOCAL_GL_CONVOLUTION_FORMAT_EXT 0x8017
+#define LOCAL_GL_CONVOLUTION_HEIGHT 0x8019
+#define LOCAL_GL_CONVOLUTION_HEIGHT_EXT 0x8019
+#define LOCAL_GL_CONVOLUTION_HINT_SGIX 0x8316
+#define LOCAL_GL_CONVOLUTION_WIDTH 0x8018
+#define LOCAL_GL_CONVOLUTION_WIDTH_EXT 0x8018
+#define LOCAL_GL_CON_0_ATI 0x8941
+#define LOCAL_GL_CON_10_ATI 0x894B
+#define LOCAL_GL_CON_11_ATI 0x894C
+#define LOCAL_GL_CON_12_ATI 0x894D
+#define LOCAL_GL_CON_13_ATI 0x894E
+#define LOCAL_GL_CON_14_ATI 0x894F
+#define LOCAL_GL_CON_15_ATI 0x8950
+#define LOCAL_GL_CON_16_ATI 0x8951
+#define LOCAL_GL_CON_17_ATI 0x8952
+#define LOCAL_GL_CON_18_ATI 0x8953
+#define LOCAL_GL_CON_19_ATI 0x8954
+#define LOCAL_GL_CON_1_ATI 0x8942
+#define LOCAL_GL_CON_20_ATI 0x8955
+#define LOCAL_GL_CON_21_ATI 0x8956
+#define LOCAL_GL_CON_22_ATI 0x8957
+#define LOCAL_GL_CON_23_ATI 0x8958
+#define LOCAL_GL_CON_24_ATI 0x8959
+#define LOCAL_GL_CON_25_ATI 0x895A
+#define LOCAL_GL_CON_26_ATI 0x895B
+#define LOCAL_GL_CON_27_ATI 0x895C
+#define LOCAL_GL_CON_28_ATI 0x895D
+#define LOCAL_GL_CON_29_ATI 0x895E
+#define LOCAL_GL_CON_2_ATI 0x8943
+#define LOCAL_GL_CON_30_ATI 0x895F
+#define LOCAL_GL_CON_31_ATI 0x8960
+#define LOCAL_GL_CON_3_ATI 0x8944
+#define LOCAL_GL_CON_4_ATI 0x8945
+#define LOCAL_GL_CON_5_ATI 0x8946
+#define LOCAL_GL_CON_6_ATI 0x8947
+#define LOCAL_GL_CON_7_ATI 0x8948
+#define LOCAL_GL_CON_8_ATI 0x8949
+#define LOCAL_GL_CON_9_ATI 0x894A
+#define LOCAL_GL_COORD_REPLACE 0x8862
+#define LOCAL_GL_COORD_REPLACE_ARB 0x8862
+#define LOCAL_GL_COORD_REPLACE_NV 0x8862
+#define LOCAL_GL_COORD_REPLACE_OES 0x8862
+#define LOCAL_GL_COPY 0x1503
+#define LOCAL_GL_COPY_INVERTED 0x150C
+#define LOCAL_GL_COPY_PIXEL_TOKEN 0x0706
+#define LOCAL_GL_COPY_READ_BUFFER 0x8F36
+#define LOCAL_GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define LOCAL_GL_COPY_READ_BUFFER_NV 0x8F36
+#define LOCAL_GL_COPY_WRITE_BUFFER 0x8F37
+#define LOCAL_GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define LOCAL_GL_COPY_WRITE_BUFFER_NV 0x8F37
+#define LOCAL_GL_COUNTER_RANGE_AMD 0x8BC1
+#define LOCAL_GL_COUNTER_TYPE_AMD 0x8BC0
+#define LOCAL_GL_COUNT_DOWN_NV 0x9089
+#define LOCAL_GL_COUNT_UP_NV 0x9088
+#define LOCAL_GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5
+#define LOCAL_GL_COVERAGE_ATTACHMENT_NV 0x8ED2
+#define LOCAL_GL_COVERAGE_AUTOMATIC_NV 0x8ED7
+#define LOCAL_GL_COVERAGE_BUFFERS_NV 0x8ED3
+#define LOCAL_GL_COVERAGE_BUFFER_BIT_NV 0x00008000
+#define LOCAL_GL_COVERAGE_COMPONENT4_NV 0x8ED1
+#define LOCAL_GL_COVERAGE_COMPONENT_NV 0x8ED0
+#define LOCAL_GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6
+#define LOCAL_GL_COVERAGE_MODULATION_NV 0x9332
+#define LOCAL_GL_COVERAGE_MODULATION_TABLE_NV 0x9331
+#define LOCAL_GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+#define LOCAL_GL_COVERAGE_SAMPLES_NV 0x8ED4
+#define LOCAL_GL_CPU_OPTIMIZED_QCOM 0x8FB1
+#define LOCAL_GL_CUBIC_CURVE_TO_NV 0x0C
+#define LOCAL_GL_CUBIC_EXT 0x8334
+#define LOCAL_GL_CUBIC_HP 0x815F
+#define LOCAL_GL_CUBIC_IMG 0x9139
+#define LOCAL_GL_CUBIC_MIPMAP_LINEAR_IMG 0x913B
+#define LOCAL_GL_CUBIC_MIPMAP_NEAREST_IMG 0x913A
+#define LOCAL_GL_CULL_FACE 0x0B44
+#define LOCAL_GL_CULL_FACE_MODE 0x0B45
+#define LOCAL_GL_CULL_FRAGMENT_NV 0x86E7
+#define LOCAL_GL_CULL_MODES_NV 0x86E0
+#define LOCAL_GL_CULL_VERTEX_EXT 0x81AA
+#define LOCAL_GL_CULL_VERTEX_EYE_POSITION_EXT 0x81AB
+#define LOCAL_GL_CULL_VERTEX_IBM 103050
+#define LOCAL_GL_CULL_VERTEX_OBJECT_POSITION_EXT 0x81AC
+#define LOCAL_GL_CURRENT_ATTRIB_NV 0x8626
+#define LOCAL_GL_CURRENT_BINORMAL_EXT 0x843C
+#define LOCAL_GL_CURRENT_BIT 0x00000001
+#define LOCAL_GL_CURRENT_COLOR 0x0B00
+#define LOCAL_GL_CURRENT_FOG_COORD 0x8453
+#define LOCAL_GL_CURRENT_FOG_COORDINATE 0x8453
+#define LOCAL_GL_CURRENT_FOG_COORDINATE_EXT 0x8453
+#define LOCAL_GL_CURRENT_INDEX 0x0B01
+#define LOCAL_GL_CURRENT_MATRIX_ARB 0x8641
+#define LOCAL_GL_CURRENT_MATRIX_INDEX_ARB 0x8845
+#define LOCAL_GL_CURRENT_MATRIX_NV 0x8641
+#define LOCAL_GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
+#define LOCAL_GL_CURRENT_MATRIX_STACK_DEPTH_NV 0x8640
+#define LOCAL_GL_CURRENT_NORMAL 0x0B02
+#define LOCAL_GL_CURRENT_OCCLUSION_QUERY_ID_NV 0x8865
+#define LOCAL_GL_CURRENT_PALETTE_MATRIX_ARB 0x8843
+#define LOCAL_GL_CURRENT_PALETTE_MATRIX_OES 0x8843
+#define LOCAL_GL_CURRENT_PROGRAM 0x8B8D
+#define LOCAL_GL_CURRENT_QUERY 0x8865
+#define LOCAL_GL_CURRENT_QUERY_ARB 0x8865
+#define LOCAL_GL_CURRENT_QUERY_EXT 0x8865
+#define LOCAL_GL_CURRENT_RASTER_COLOR 0x0B04
+#define LOCAL_GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define LOCAL_GL_CURRENT_RASTER_INDEX 0x0B05
+#define LOCAL_GL_CURRENT_RASTER_NORMAL_SGIX 0x8406
+#define LOCAL_GL_CURRENT_RASTER_POSITION 0x0B07
+#define LOCAL_GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define LOCAL_GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define LOCAL_GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define LOCAL_GL_CURRENT_SECONDARY_COLOR 0x8459
+#define LOCAL_GL_CURRENT_SECONDARY_COLOR_EXT 0x8459
+#define LOCAL_GL_CURRENT_TANGENT_EXT 0x843B
+#define LOCAL_GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define LOCAL_GL_CURRENT_TIME_NV 0x8E28
+#define LOCAL_GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define LOCAL_GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
+#define LOCAL_GL_CURRENT_VERTEX_EXT 0x87E2
+#define LOCAL_GL_CURRENT_VERTEX_WEIGHT_EXT 0x850B
+#define LOCAL_GL_CURRENT_WEIGHT_ARB 0x86A8
+#define LOCAL_GL_CW 0x0900
+#define LOCAL_GL_D3D12_FENCE_VALUE_EXT 0x9595
+#define LOCAL_GL_DARKEN 0x9297
+#define LOCAL_GL_DARKEN_KHR 0x9297
+#define LOCAL_GL_DARKEN_NV 0x9297
+#define LOCAL_GL_DATA_BUFFER_AMD 0x9151
+#define LOCAL_GL_DEBUG_ASSERT_MESA 0x875B
+#define LOCAL_GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define LOCAL_GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244
+#define LOCAL_GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244
+#define LOCAL_GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define LOCAL_GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245
+#define LOCAL_GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245
+#define LOCAL_GL_DEBUG_CATEGORY_API_ERROR_AMD 0x9149
+#define LOCAL_GL_DEBUG_CATEGORY_APPLICATION_AMD 0x914F
+#define LOCAL_GL_DEBUG_CATEGORY_DEPRECATION_AMD 0x914B
+#define LOCAL_GL_DEBUG_CATEGORY_OTHER_AMD 0x9150
+#define LOCAL_GL_DEBUG_CATEGORY_PERFORMANCE_AMD 0x914D
+#define LOCAL_GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD 0x914E
+#define LOCAL_GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD 0x914C
+#define LOCAL_GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD 0x914A
+#define LOCAL_GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define LOCAL_GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D
+#define LOCAL_GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define LOCAL_GL_DEBUG_LOGGED_MESSAGES_AMD 0x9145
+#define LOCAL_GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145
+#define LOCAL_GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145
+#define LOCAL_GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define LOCAL_GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243
+#define LOCAL_GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243
+#define LOCAL_GL_DEBUG_OBJECT_MESA 0x8759
+#define LOCAL_GL_DEBUG_OUTPUT 0x92E0
+#define LOCAL_GL_DEBUG_OUTPUT_KHR 0x92E0
+#define LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242
+#define LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242
+#define LOCAL_GL_DEBUG_PRINT_MESA 0x875A
+#define LOCAL_GL_DEBUG_SEVERITY_HIGH 0x9146
+#define LOCAL_GL_DEBUG_SEVERITY_HIGH_AMD 0x9146
+#define LOCAL_GL_DEBUG_SEVERITY_HIGH_ARB 0x9146
+#define LOCAL_GL_DEBUG_SEVERITY_HIGH_KHR 0x9146
+#define LOCAL_GL_DEBUG_SEVERITY_LOW 0x9148
+#define LOCAL_GL_DEBUG_SEVERITY_LOW_AMD 0x9148
+#define LOCAL_GL_DEBUG_SEVERITY_LOW_ARB 0x9148
+#define LOCAL_GL_DEBUG_SEVERITY_LOW_KHR 0x9148
+#define LOCAL_GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define LOCAL_GL_DEBUG_SEVERITY_MEDIUM_AMD 0x9147
+#define LOCAL_GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147
+#define LOCAL_GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147
+#define LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B
+#define LOCAL_GL_DEBUG_SOURCE_API 0x8246
+#define LOCAL_GL_DEBUG_SOURCE_API_ARB 0x8246
+#define LOCAL_GL_DEBUG_SOURCE_API_KHR 0x8246
+#define LOCAL_GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define LOCAL_GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A
+#define LOCAL_GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A
+#define LOCAL_GL_DEBUG_SOURCE_OTHER 0x824B
+#define LOCAL_GL_DEBUG_SOURCE_OTHER_ARB 0x824B
+#define LOCAL_GL_DEBUG_SOURCE_OTHER_KHR 0x824B
+#define LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248
+#define LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248
+#define LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249
+#define LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249
+#define LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247
+#define LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247
+#define LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D
+#define LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D
+#define LOCAL_GL_DEBUG_TYPE_ERROR 0x824C
+#define LOCAL_GL_DEBUG_TYPE_ERROR_ARB 0x824C
+#define LOCAL_GL_DEBUG_TYPE_ERROR_KHR 0x824C
+#define LOCAL_GL_DEBUG_TYPE_MARKER 0x8268
+#define LOCAL_GL_DEBUG_TYPE_MARKER_KHR 0x8268
+#define LOCAL_GL_DEBUG_TYPE_OTHER 0x8251
+#define LOCAL_GL_DEBUG_TYPE_OTHER_ARB 0x8251
+#define LOCAL_GL_DEBUG_TYPE_OTHER_KHR 0x8251
+#define LOCAL_GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define LOCAL_GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250
+#define LOCAL_GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250
+#define LOCAL_GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define LOCAL_GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A
+#define LOCAL_GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define LOCAL_GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F
+#define LOCAL_GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F
+#define LOCAL_GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define LOCAL_GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269
+#define LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E
+#define LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E
+#define LOCAL_GL_DECAL 0x2101
+#define LOCAL_GL_DECODE_EXT 0x8A49
+#define LOCAL_GL_DECR 0x1E03
+#define LOCAL_GL_DECR_WRAP 0x8508
+#define LOCAL_GL_DECR_WRAP_EXT 0x8508
+#define LOCAL_GL_DECR_WRAP_OES 0x8508
+#define LOCAL_GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581
+#define LOCAL_GL_DEFORMATIONS_MASK_SGIX 0x8196
+#define LOCAL_GL_DELETE_STATUS 0x8B80
+#define LOCAL_GL_DEPENDENT_AR_TEXTURE_2D_NV 0x86E9
+#define LOCAL_GL_DEPENDENT_GB_TEXTURE_2D_NV 0x86EA
+#define LOCAL_GL_DEPENDENT_HILO_TEXTURE_2D_NV 0x8858
+#define LOCAL_GL_DEPENDENT_RGB_TEXTURE_3D_NV 0x8859
+#define LOCAL_GL_DEPENDENT_RGB_TEXTURE_CUBE_MAP_NV 0x885A
+#define LOCAL_GL_DEPTH 0x1801
+#define LOCAL_GL_DEPTH24_STENCIL8 0x88F0
+#define LOCAL_GL_DEPTH24_STENCIL8_EXT 0x88F0
+#define LOCAL_GL_DEPTH24_STENCIL8_OES 0x88F0
+#define LOCAL_GL_DEPTH32F_STENCIL8 0x8CAD
+#define LOCAL_GL_DEPTH32F_STENCIL8_NV 0x8DAC
+#define LOCAL_GL_DEPTH_ATTACHMENT 0x8D00
+#define LOCAL_GL_DEPTH_ATTACHMENT_EXT 0x8D00
+#define LOCAL_GL_DEPTH_ATTACHMENT_OES 0x8D00
+#define LOCAL_GL_DEPTH_BIAS 0x0D1F
+#define LOCAL_GL_DEPTH_BITS 0x0D56
+#define LOCAL_GL_DEPTH_BOUNDS_EXT 0x8891
+#define LOCAL_GL_DEPTH_BOUNDS_TEST_EXT 0x8890
+#define LOCAL_GL_DEPTH_BUFFER_BIT 0x00000100
+#define LOCAL_GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100
+#define LOCAL_GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200
+#define LOCAL_GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400
+#define LOCAL_GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800
+#define LOCAL_GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000
+#define LOCAL_GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000
+#define LOCAL_GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000
+#define LOCAL_GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000
+#define LOCAL_GL_DEPTH_BUFFER_FLOAT_MODE_NV 0x8DAF
+#define LOCAL_GL_DEPTH_CLAMP 0x864F
+#define LOCAL_GL_DEPTH_CLAMP_EXT 0x864F
+#define LOCAL_GL_DEPTH_CLAMP_FAR_AMD 0x901F
+#define LOCAL_GL_DEPTH_CLAMP_NEAR_AMD 0x901E
+#define LOCAL_GL_DEPTH_CLAMP_NV 0x864F
+#define LOCAL_GL_DEPTH_CLEAR_VALUE 0x0B73
+#define LOCAL_GL_DEPTH_COMPONENT 0x1902
+#define LOCAL_GL_DEPTH_COMPONENT16 0x81A5
+#define LOCAL_GL_DEPTH_COMPONENT16_ARB 0x81A5
+#define LOCAL_GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C
+#define LOCAL_GL_DEPTH_COMPONENT16_OES 0x81A5
+#define LOCAL_GL_DEPTH_COMPONENT16_SGIX 0x81A5
+#define LOCAL_GL_DEPTH_COMPONENT24 0x81A6
+#define LOCAL_GL_DEPTH_COMPONENT24_ARB 0x81A6
+#define LOCAL_GL_DEPTH_COMPONENT24_OES 0x81A6
+#define LOCAL_GL_DEPTH_COMPONENT24_SGIX 0x81A6
+#define LOCAL_GL_DEPTH_COMPONENT32 0x81A7
+#define LOCAL_GL_DEPTH_COMPONENT32F 0x8CAC
+#define LOCAL_GL_DEPTH_COMPONENT32F_NV 0x8DAB
+#define LOCAL_GL_DEPTH_COMPONENT32_ARB 0x81A7
+#define LOCAL_GL_DEPTH_COMPONENT32_OES 0x81A7
+#define LOCAL_GL_DEPTH_COMPONENT32_SGIX 0x81A7
+#define LOCAL_GL_DEPTH_COMPONENTS 0x8284
+#define LOCAL_GL_DEPTH_EXT 0x1801
+#define LOCAL_GL_DEPTH_FUNC 0x0B74
+#define LOCAL_GL_DEPTH_PASS_INSTRUMENT_COUNTERS_SGIX 0x8311
+#define LOCAL_GL_DEPTH_PASS_INSTRUMENT_MAX_SGIX 0x8312
+#define LOCAL_GL_DEPTH_PASS_INSTRUMENT_SGIX 0x8310
+#define LOCAL_GL_DEPTH_RANGE 0x0B70
+#define LOCAL_GL_DEPTH_RENDERABLE 0x8287
+#define LOCAL_GL_DEPTH_SAMPLES_NV 0x932D
+#define LOCAL_GL_DEPTH_SCALE 0x0D1E
+#define LOCAL_GL_DEPTH_STENCIL 0x84F9
+#define LOCAL_GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define LOCAL_GL_DEPTH_STENCIL_EXT 0x84F9
+#define LOCAL_GL_DEPTH_STENCIL_MESA 0x8750
+#define LOCAL_GL_DEPTH_STENCIL_NV 0x84F9
+#define LOCAL_GL_DEPTH_STENCIL_OES 0x84F9
+#define LOCAL_GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define LOCAL_GL_DEPTH_STENCIL_TO_BGRA_NV 0x886F
+#define LOCAL_GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E
+#define LOCAL_GL_DEPTH_TEST 0x0B71
+#define LOCAL_GL_DEPTH_TEXTURE_MODE 0x884B
+#define LOCAL_GL_DEPTH_TEXTURE_MODE_ARB 0x884B
+#define LOCAL_GL_DEPTH_WRITEMASK 0x0B72
+#define LOCAL_GL_DETACHED_BUFFERS_NV 0x95AB
+#define LOCAL_GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9
+#define LOCAL_GL_DETACHED_TEXTURES_NV 0x95AA
+#define LOCAL_GL_DETAIL_TEXTURE_2D_BINDING_SGIS 0x8096
+#define LOCAL_GL_DETAIL_TEXTURE_2D_SGIS 0x8095
+#define LOCAL_GL_DETAIL_TEXTURE_FUNC_POINTS_SGIS 0x809C
+#define LOCAL_GL_DETAIL_TEXTURE_LEVEL_SGIS 0x809A
+#define LOCAL_GL_DETAIL_TEXTURE_MODE_SGIS 0x809B
+#define LOCAL_GL_DEVICE_LUID_EXT 0x9599
+#define LOCAL_GL_DEVICE_NODE_MASK_EXT 0x959A
+#define LOCAL_GL_DEVICE_UUID_EXT 0x9597
+#define LOCAL_GL_DIFFERENCE 0x929E
+#define LOCAL_GL_DIFFERENCE_KHR 0x929E
+#define LOCAL_GL_DIFFERENCE_NV 0x929E
+#define LOCAL_GL_DIFFUSE 0x1201
+#define LOCAL_GL_DISCARD_ATI 0x8763
+#define LOCAL_GL_DISCARD_NV 0x8530
+#define LOCAL_GL_DISCRETE_AMD 0x9006
+#define LOCAL_GL_DISJOINT_NV 0x9283
+#define LOCAL_GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define LOCAL_GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define LOCAL_GL_DISPLAY_LIST 0x82E7
+#define LOCAL_GL_DISTANCE_ATTENUATION_EXT 0x8129
+#define LOCAL_GL_DISTANCE_ATTENUATION_SGIS 0x8129
+#define LOCAL_GL_DITHER 0x0BD0
+#define LOCAL_GL_DMP_PROGRAM_BINARY_DMP 0x9253
+#define LOCAL_GL_DOMAIN 0x0A02
+#define LOCAL_GL_DONT_CARE 0x1100
+#define LOCAL_GL_DOT2_ADD_ATI 0x896C
+#define LOCAL_GL_DOT3_ATI 0x8966
+#define LOCAL_GL_DOT3_RGB 0x86AE
+#define LOCAL_GL_DOT3_RGBA 0x86AF
+#define LOCAL_GL_DOT3_RGBA_ARB 0x86AF
+#define LOCAL_GL_DOT3_RGBA_EXT 0x8741
+#define LOCAL_GL_DOT3_RGBA_IMG 0x86AF
+#define LOCAL_GL_DOT3_RGB_ARB 0x86AE
+#define LOCAL_GL_DOT3_RGB_EXT 0x8740
+#define LOCAL_GL_DOT4_ATI 0x8967
+#define LOCAL_GL_DOT_PRODUCT_AFFINE_DEPTH_REPLACE_NV 0x885D
+#define LOCAL_GL_DOT_PRODUCT_CONST_EYE_REFLECT_CUBE_MAP_NV 0x86F3
+#define LOCAL_GL_DOT_PRODUCT_DEPTH_REPLACE_NV 0x86ED
+#define LOCAL_GL_DOT_PRODUCT_DIFFUSE_CUBE_MAP_NV 0x86F1
+#define LOCAL_GL_DOT_PRODUCT_NV 0x86EC
+#define LOCAL_GL_DOT_PRODUCT_PASS_THROUGH_NV 0x885B
+#define LOCAL_GL_DOT_PRODUCT_REFLECT_CUBE_MAP_NV 0x86F2
+#define LOCAL_GL_DOT_PRODUCT_TEXTURE_1D_NV 0x885C
+#define LOCAL_GL_DOT_PRODUCT_TEXTURE_2D_NV 0x86EE
+#define LOCAL_GL_DOT_PRODUCT_TEXTURE_3D_NV 0x86EF
+#define LOCAL_GL_DOT_PRODUCT_TEXTURE_CUBE_MAP_NV 0x86F0
+#define LOCAL_GL_DOT_PRODUCT_TEXTURE_RECTANGLE_NV 0x864E
+#define LOCAL_GL_DOUBLE 0x140A
+#define LOCAL_GL_DOUBLEBUFFER 0x0C32
+#define LOCAL_GL_DOUBLE_EXT 0x140A
+#define LOCAL_GL_DOUBLE_MAT2 0x8F46
+#define LOCAL_GL_DOUBLE_MAT2_EXT 0x8F46
+#define LOCAL_GL_DOUBLE_MAT2x3 0x8F49
+#define LOCAL_GL_DOUBLE_MAT2x3_EXT 0x8F49
+#define LOCAL_GL_DOUBLE_MAT2x4 0x8F4A
+#define LOCAL_GL_DOUBLE_MAT2x4_EXT 0x8F4A
+#define LOCAL_GL_DOUBLE_MAT3 0x8F47
+#define LOCAL_GL_DOUBLE_MAT3_EXT 0x8F47
+#define LOCAL_GL_DOUBLE_MAT3x2 0x8F4B
+#define LOCAL_GL_DOUBLE_MAT3x2_EXT 0x8F4B
+#define LOCAL_GL_DOUBLE_MAT3x4 0x8F4C
+#define LOCAL_GL_DOUBLE_MAT3x4_EXT 0x8F4C
+#define LOCAL_GL_DOUBLE_MAT4 0x8F48
+#define LOCAL_GL_DOUBLE_MAT4_EXT 0x8F48
+#define LOCAL_GL_DOUBLE_MAT4x2 0x8F4D
+#define LOCAL_GL_DOUBLE_MAT4x2_EXT 0x8F4D
+#define LOCAL_GL_DOUBLE_MAT4x3 0x8F4E
+#define LOCAL_GL_DOUBLE_MAT4x3_EXT 0x8F4E
+#define LOCAL_GL_DOUBLE_VEC2 0x8FFC
+#define LOCAL_GL_DOUBLE_VEC2_EXT 0x8FFC
+#define LOCAL_GL_DOUBLE_VEC3 0x8FFD
+#define LOCAL_GL_DOUBLE_VEC3_EXT 0x8FFD
+#define LOCAL_GL_DOUBLE_VEC4 0x8FFE
+#define LOCAL_GL_DOUBLE_VEC4_EXT 0x8FFE
+#define LOCAL_GL_DOWNSAMPLE_SCALES_IMG 0x913E
+#define LOCAL_GL_DRAW_ARRAYS_COMMAND_NV 0x0003
+#define LOCAL_GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV 0x0007
+#define LOCAL_GL_DRAW_ARRAYS_STRIP_COMMAND_NV 0x0005
+#define LOCAL_GL_DRAW_BUFFER 0x0C01
+#define LOCAL_GL_DRAW_BUFFER0 0x8825
+#define LOCAL_GL_DRAW_BUFFER0_ARB 0x8825
+#define LOCAL_GL_DRAW_BUFFER0_ATI 0x8825
+#define LOCAL_GL_DRAW_BUFFER0_EXT 0x8825
+#define LOCAL_GL_DRAW_BUFFER0_NV 0x8825
+#define LOCAL_GL_DRAW_BUFFER1 0x8826
+#define LOCAL_GL_DRAW_BUFFER10 0x882F
+#define LOCAL_GL_DRAW_BUFFER10_ARB 0x882F
+#define LOCAL_GL_DRAW_BUFFER10_ATI 0x882F
+#define LOCAL_GL_DRAW_BUFFER10_EXT 0x882F
+#define LOCAL_GL_DRAW_BUFFER10_NV 0x882F
+#define LOCAL_GL_DRAW_BUFFER11 0x8830
+#define LOCAL_GL_DRAW_BUFFER11_ARB 0x8830
+#define LOCAL_GL_DRAW_BUFFER11_ATI 0x8830
+#define LOCAL_GL_DRAW_BUFFER11_EXT 0x8830
+#define LOCAL_GL_DRAW_BUFFER11_NV 0x8830
+#define LOCAL_GL_DRAW_BUFFER12 0x8831
+#define LOCAL_GL_DRAW_BUFFER12_ARB 0x8831
+#define LOCAL_GL_DRAW_BUFFER12_ATI 0x8831
+#define LOCAL_GL_DRAW_BUFFER12_EXT 0x8831
+#define LOCAL_GL_DRAW_BUFFER12_NV 0x8831
+#define LOCAL_GL_DRAW_BUFFER13 0x8832
+#define LOCAL_GL_DRAW_BUFFER13_ARB 0x8832
+#define LOCAL_GL_DRAW_BUFFER13_ATI 0x8832
+#define LOCAL_GL_DRAW_BUFFER13_EXT 0x8832
+#define LOCAL_GL_DRAW_BUFFER13_NV 0x8832
+#define LOCAL_GL_DRAW_BUFFER14 0x8833
+#define LOCAL_GL_DRAW_BUFFER14_ARB 0x8833
+#define LOCAL_GL_DRAW_BUFFER14_ATI 0x8833
+#define LOCAL_GL_DRAW_BUFFER14_EXT 0x8833
+#define LOCAL_GL_DRAW_BUFFER14_NV 0x8833
+#define LOCAL_GL_DRAW_BUFFER15 0x8834
+#define LOCAL_GL_DRAW_BUFFER15_ARB 0x8834
+#define LOCAL_GL_DRAW_BUFFER15_ATI 0x8834
+#define LOCAL_GL_DRAW_BUFFER15_EXT 0x8834
+#define LOCAL_GL_DRAW_BUFFER15_NV 0x8834
+#define LOCAL_GL_DRAW_BUFFER1_ARB 0x8826
+#define LOCAL_GL_DRAW_BUFFER1_ATI 0x8826
+#define LOCAL_GL_DRAW_BUFFER1_EXT 0x8826
+#define LOCAL_GL_DRAW_BUFFER1_NV 0x8826
+#define LOCAL_GL_DRAW_BUFFER2 0x8827
+#define LOCAL_GL_DRAW_BUFFER2_ARB 0x8827
+#define LOCAL_GL_DRAW_BUFFER2_ATI 0x8827
+#define LOCAL_GL_DRAW_BUFFER2_EXT 0x8827
+#define LOCAL_GL_DRAW_BUFFER2_NV 0x8827
+#define LOCAL_GL_DRAW_BUFFER3 0x8828
+#define LOCAL_GL_DRAW_BUFFER3_ARB 0x8828
+#define LOCAL_GL_DRAW_BUFFER3_ATI 0x8828
+#define LOCAL_GL_DRAW_BUFFER3_EXT 0x8828
+#define LOCAL_GL_DRAW_BUFFER3_NV 0x8828
+#define LOCAL_GL_DRAW_BUFFER4 0x8829
+#define LOCAL_GL_DRAW_BUFFER4_ARB 0x8829
+#define LOCAL_GL_DRAW_BUFFER4_ATI 0x8829
+#define LOCAL_GL_DRAW_BUFFER4_EXT 0x8829
+#define LOCAL_GL_DRAW_BUFFER4_NV 0x8829
+#define LOCAL_GL_DRAW_BUFFER5 0x882A
+#define LOCAL_GL_DRAW_BUFFER5_ARB 0x882A
+#define LOCAL_GL_DRAW_BUFFER5_ATI 0x882A
+#define LOCAL_GL_DRAW_BUFFER5_EXT 0x882A
+#define LOCAL_GL_DRAW_BUFFER5_NV 0x882A
+#define LOCAL_GL_DRAW_BUFFER6 0x882B
+#define LOCAL_GL_DRAW_BUFFER6_ARB 0x882B
+#define LOCAL_GL_DRAW_BUFFER6_ATI 0x882B
+#define LOCAL_GL_DRAW_BUFFER6_EXT 0x882B
+#define LOCAL_GL_DRAW_BUFFER6_NV 0x882B
+#define LOCAL_GL_DRAW_BUFFER7 0x882C
+#define LOCAL_GL_DRAW_BUFFER7_ARB 0x882C
+#define LOCAL_GL_DRAW_BUFFER7_ATI 0x882C
+#define LOCAL_GL_DRAW_BUFFER7_EXT 0x882C
+#define LOCAL_GL_DRAW_BUFFER7_NV 0x882C
+#define LOCAL_GL_DRAW_BUFFER8 0x882D
+#define LOCAL_GL_DRAW_BUFFER8_ARB 0x882D
+#define LOCAL_GL_DRAW_BUFFER8_ATI 0x882D
+#define LOCAL_GL_DRAW_BUFFER8_EXT 0x882D
+#define LOCAL_GL_DRAW_BUFFER8_NV 0x882D
+#define LOCAL_GL_DRAW_BUFFER9 0x882E
+#define LOCAL_GL_DRAW_BUFFER9_ARB 0x882E
+#define LOCAL_GL_DRAW_BUFFER9_ATI 0x882E
+#define LOCAL_GL_DRAW_BUFFER9_EXT 0x882E
+#define LOCAL_GL_DRAW_BUFFER9_NV 0x882E
+#define LOCAL_GL_DRAW_BUFFER_EXT 0x0C01
+#define LOCAL_GL_DRAW_ELEMENTS_COMMAND_NV 0x0002
+#define LOCAL_GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV 0x0006
+#define LOCAL_GL_DRAW_ELEMENTS_STRIP_COMMAND_NV 0x0004
+#define LOCAL_GL_DRAW_FRAMEBUFFER 0x8CA9
+#define LOCAL_GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9
+#define LOCAL_GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9
+#define LOCAL_GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6
+#define LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6
+#define LOCAL_GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#define LOCAL_GL_DRAW_FRAMEBUFFER_NV 0x8CA9
+#define LOCAL_GL_DRAW_INDIRECT_ADDRESS_NV 0x8F41
+#define LOCAL_GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define LOCAL_GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define LOCAL_GL_DRAW_INDIRECT_LENGTH_NV 0x8F42
+#define LOCAL_GL_DRAW_INDIRECT_UNIFIED_NV 0x8F40
+#define LOCAL_GL_DRAW_PIXELS_APPLE 0x8A0A
+#define LOCAL_GL_DRAW_PIXEL_TOKEN 0x0705
+#define LOCAL_GL_DRIVER_UUID_EXT 0x9598
+#define LOCAL_GL_DSDT8_MAG8_INTENSITY8_NV 0x870B
+#define LOCAL_GL_DSDT8_MAG8_NV 0x870A
+#define LOCAL_GL_DSDT8_NV 0x8709
+#define LOCAL_GL_DSDT_MAG_INTENSITY_NV 0x86DC
+#define LOCAL_GL_DSDT_MAG_NV 0x86F6
+#define LOCAL_GL_DSDT_MAG_VIB_NV 0x86F7
+#define LOCAL_GL_DSDT_NV 0x86F5
+#define LOCAL_GL_DST_ALPHA 0x0304
+#define LOCAL_GL_DST_ATOP_NV 0x928F
+#define LOCAL_GL_DST_COLOR 0x0306
+#define LOCAL_GL_DST_IN_NV 0x928B
+#define LOCAL_GL_DST_NV 0x9287
+#define LOCAL_GL_DST_OUT_NV 0x928D
+#define LOCAL_GL_DST_OVER_NV 0x9289
+#define LOCAL_GL_DS_BIAS_NV 0x8716
+#define LOCAL_GL_DS_SCALE_NV 0x8710
+#define LOCAL_GL_DT_BIAS_NV 0x8717
+#define LOCAL_GL_DT_SCALE_NV 0x8711
+#define LOCAL_GL_DU8DV8_ATI 0x877A
+#define LOCAL_GL_DUAL_ALPHA12_SGIS 0x8112
+#define LOCAL_GL_DUAL_ALPHA16_SGIS 0x8113
+#define LOCAL_GL_DUAL_ALPHA4_SGIS 0x8110
+#define LOCAL_GL_DUAL_ALPHA8_SGIS 0x8111
+#define LOCAL_GL_DUAL_INTENSITY12_SGIS 0x811A
+#define LOCAL_GL_DUAL_INTENSITY16_SGIS 0x811B
+#define LOCAL_GL_DUAL_INTENSITY4_SGIS 0x8118
+#define LOCAL_GL_DUAL_INTENSITY8_SGIS 0x8119
+#define LOCAL_GL_DUAL_LUMINANCE12_SGIS 0x8116
+#define LOCAL_GL_DUAL_LUMINANCE16_SGIS 0x8117
+#define LOCAL_GL_DUAL_LUMINANCE4_SGIS 0x8114
+#define LOCAL_GL_DUAL_LUMINANCE8_SGIS 0x8115
+#define LOCAL_GL_DUAL_LUMINANCE_ALPHA4_SGIS 0x811C
+#define LOCAL_GL_DUAL_LUMINANCE_ALPHA8_SGIS 0x811D
+#define LOCAL_GL_DUAL_TEXTURE_SELECT_SGIS 0x8124
+#define LOCAL_GL_DUDV_ATI 0x8779
+#define LOCAL_GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2
+#define LOCAL_GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4
+#define LOCAL_GL_DYNAMIC_ATI 0x8761
+#define LOCAL_GL_DYNAMIC_COPY 0x88EA
+#define LOCAL_GL_DYNAMIC_COPY_ARB 0x88EA
+#define LOCAL_GL_DYNAMIC_DRAW 0x88E8
+#define LOCAL_GL_DYNAMIC_DRAW_ARB 0x88E8
+#define LOCAL_GL_DYNAMIC_READ 0x88E9
+#define LOCAL_GL_DYNAMIC_READ_ARB 0x88E9
+#define LOCAL_GL_DYNAMIC_STORAGE_BIT 0x0100
+#define LOCAL_GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
+#define LOCAL_GL_EDGEFLAG_BIT_PGI 0x00040000
+#define LOCAL_GL_EDGE_FLAG 0x0B43
+#define LOCAL_GL_EDGE_FLAG_ARRAY 0x8079
+#define LOCAL_GL_EDGE_FLAG_ARRAY_ADDRESS_NV 0x8F26
+#define LOCAL_GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define LOCAL_GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define LOCAL_GL_EDGE_FLAG_ARRAY_COUNT_EXT 0x808D
+#define LOCAL_GL_EDGE_FLAG_ARRAY_EXT 0x8079
+#define LOCAL_GL_EDGE_FLAG_ARRAY_LENGTH_NV 0x8F30
+#define LOCAL_GL_EDGE_FLAG_ARRAY_LIST_IBM 103075
+#define LOCAL_GL_EDGE_FLAG_ARRAY_LIST_STRIDE_IBM 103085
+#define LOCAL_GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define LOCAL_GL_EDGE_FLAG_ARRAY_POINTER_EXT 0x8093
+#define LOCAL_GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define LOCAL_GL_EDGE_FLAG_ARRAY_STRIDE_EXT 0x808C
+#define LOCAL_GL_EFFECTIVE_RASTER_SAMPLES_EXT 0x932C
+#define LOCAL_GL_EIGHTH_BIT_ATI 0x00000020
+#define LOCAL_GL_ELEMENT_ADDRESS_COMMAND_NV 0x0008
+#define LOCAL_GL_ELEMENT_ARRAY_ADDRESS_NV 0x8F29
+#define LOCAL_GL_ELEMENT_ARRAY_APPLE 0x8A0C
+#define LOCAL_GL_ELEMENT_ARRAY_ATI 0x8768
+#define LOCAL_GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define LOCAL_GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002
+#define LOCAL_GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define LOCAL_GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define LOCAL_GL_ELEMENT_ARRAY_LENGTH_NV 0x8F33
+#define LOCAL_GL_ELEMENT_ARRAY_POINTER_APPLE 0x8A0E
+#define LOCAL_GL_ELEMENT_ARRAY_POINTER_ATI 0x876A
+#define LOCAL_GL_ELEMENT_ARRAY_TYPE_APPLE 0x8A0D
+#define LOCAL_GL_ELEMENT_ARRAY_TYPE_ATI 0x8769
+#define LOCAL_GL_ELEMENT_ARRAY_UNIFIED_NV 0x8F1F
+#define LOCAL_GL_EMBOSS_CONSTANT_NV 0x855E
+#define LOCAL_GL_EMBOSS_LIGHT_NV 0x855D
+#define LOCAL_GL_EMBOSS_MAP_NV 0x855F
+#define LOCAL_GL_EMISSION 0x1600
+#define LOCAL_GL_ENABLE_BIT 0x00002000
+#define LOCAL_GL_EQUAL 0x0202
+#define LOCAL_GL_EQUIV 0x1509
+#define LOCAL_GL_ETC1_RGB8_OES 0x8D64
+#define LOCAL_GL_ETC1_SRGB8_NV 0x88EE
+#define LOCAL_GL_EVAL_2D_NV 0x86C0
+#define LOCAL_GL_EVAL_BIT 0x00010000
+#define LOCAL_GL_EVAL_FRACTIONAL_TESSELLATION_NV 0x86C5
+#define LOCAL_GL_EVAL_TRIANGULAR_2D_NV 0x86C1
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB0_NV 0x86C6
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB10_NV 0x86D0
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB11_NV 0x86D1
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB12_NV 0x86D2
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB13_NV 0x86D3
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB14_NV 0x86D4
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB15_NV 0x86D5
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB1_NV 0x86C7
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB2_NV 0x86C8
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB3_NV 0x86C9
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB4_NV 0x86CA
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB5_NV 0x86CB
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB6_NV 0x86CC
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB7_NV 0x86CD
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB8_NV 0x86CE
+#define LOCAL_GL_EVAL_VERTEX_ATTRIB9_NV 0x86CF
+#define LOCAL_GL_EXCLUSION 0x92A0
+#define LOCAL_GL_EXCLUSION_KHR 0x92A0
+#define LOCAL_GL_EXCLUSION_NV 0x92A0
+#define LOCAL_GL_EXCLUSIVE_EXT 0x8F11
+#define LOCAL_GL_EXP 0x0800
+#define LOCAL_GL_EXP2 0x0801
+#define LOCAL_GL_EXPAND_NEGATE_NV 0x8539
+#define LOCAL_GL_EXPAND_NORMAL_NV 0x8538
+#define LOCAL_GL_EXTENSIONS 0x1F03
+#define LOCAL_GL_EXTERNAL_STORAGE_BIT_NVX 0x2000
+#define LOCAL_GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160
+#define LOCAL_GL_EYE_DISTANCE_TO_LINE_SGIS 0x81F2
+#define LOCAL_GL_EYE_DISTANCE_TO_POINT_SGIS 0x81F0
+#define LOCAL_GL_EYE_LINEAR 0x2400
+#define LOCAL_GL_EYE_LINEAR_NV 0x2400
+#define LOCAL_GL_EYE_LINE_SGIS 0x81F6
+#define LOCAL_GL_EYE_PLANE 0x2502
+#define LOCAL_GL_EYE_PLANE_ABSOLUTE_NV 0x855C
+#define LOCAL_GL_EYE_POINT_SGIS 0x81F4
+#define LOCAL_GL_EYE_RADIAL_NV 0x855B
+#define LOCAL_GL_E_TIMES_F_NV 0x8531
+#define LOCAL_GL_FACTOR_ALPHA_MODULATE_IMG 0x8C07
+#define LOCAL_GL_FACTOR_MAX_AMD 0x901D
+#define LOCAL_GL_FACTOR_MIN_AMD 0x901C
+#define LOCAL_GL_FAILURE_NV 0x9030
+#define LOCAL_GL_FALSE 0
+#define LOCAL_GL_FASTEST 0x1101
+#define LOCAL_GL_FEEDBACK 0x1C01
+#define LOCAL_GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define LOCAL_GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define LOCAL_GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define LOCAL_GL_FENCE_APPLE 0x8A0B
+#define LOCAL_GL_FENCE_CONDITION_NV 0x84F4
+#define LOCAL_GL_FENCE_STATUS_NV 0x84F3
+#define LOCAL_GL_FETCH_PER_SAMPLE_ARM 0x8F65
+#define LOCAL_GL_FIELDS_NV 0x8E27
+#define LOCAL_GL_FIELD_LOWER_NV 0x9023
+#define LOCAL_GL_FIELD_UPPER_NV 0x9022
+#define LOCAL_GL_FILE_NAME_NV 0x9074
+#define LOCAL_GL_FILL 0x1B02
+#define LOCAL_GL_FILL_NV 0x1B02
+#define LOCAL_GL_FILL_RECTANGLE_NV 0x933C
+#define LOCAL_GL_FILTER 0x829A
+#define LOCAL_GL_FILTER4_SGIS 0x8146
+#define LOCAL_GL_FIRST_TO_REST_NV 0x90AF
+#define LOCAL_GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define LOCAL_GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D
+#define LOCAL_GL_FIRST_VERTEX_CONVENTION_OES 0x8E4D
+#define LOCAL_GL_FIXED 0x140C
+#define LOCAL_GL_FIXED_OES 0x140C
+#define LOCAL_GL_FIXED_ONLY 0x891D
+#define LOCAL_GL_FIXED_ONLY_ARB 0x891D
+#define LOCAL_GL_FLAT 0x1D00
+#define LOCAL_GL_FLOAT 0x1406
+#define LOCAL_GL_FLOAT16_MAT2_AMD 0x91C5
+#define LOCAL_GL_FLOAT16_MAT2x3_AMD 0x91C8
+#define LOCAL_GL_FLOAT16_MAT2x4_AMD 0x91C9
+#define LOCAL_GL_FLOAT16_MAT3_AMD 0x91C6
+#define LOCAL_GL_FLOAT16_MAT3x2_AMD 0x91CA
+#define LOCAL_GL_FLOAT16_MAT3x4_AMD 0x91CB
+#define LOCAL_GL_FLOAT16_MAT4_AMD 0x91C7
+#define LOCAL_GL_FLOAT16_MAT4x2_AMD 0x91CC
+#define LOCAL_GL_FLOAT16_MAT4x3_AMD 0x91CD
+#define LOCAL_GL_FLOAT16_NV 0x8FF8
+#define LOCAL_GL_FLOAT16_VEC2_NV 0x8FF9
+#define LOCAL_GL_FLOAT16_VEC3_NV 0x8FFA
+#define LOCAL_GL_FLOAT16_VEC4_NV 0x8FFB
+#define LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV 0x8DAD
+#define LOCAL_GL_FLOAT_CLEAR_COLOR_VALUE_NV 0x888D
+#define LOCAL_GL_FLOAT_MAT2 0x8B5A
+#define LOCAL_GL_FLOAT_MAT2_ARB 0x8B5A
+#define LOCAL_GL_FLOAT_MAT2x3 0x8B65
+#define LOCAL_GL_FLOAT_MAT2x3_NV 0x8B65
+#define LOCAL_GL_FLOAT_MAT2x4 0x8B66
+#define LOCAL_GL_FLOAT_MAT2x4_NV 0x8B66
+#define LOCAL_GL_FLOAT_MAT3 0x8B5B
+#define LOCAL_GL_FLOAT_MAT3_ARB 0x8B5B
+#define LOCAL_GL_FLOAT_MAT3x2 0x8B67
+#define LOCAL_GL_FLOAT_MAT3x2_NV 0x8B67
+#define LOCAL_GL_FLOAT_MAT3x4 0x8B68
+#define LOCAL_GL_FLOAT_MAT3x4_NV 0x8B68
+#define LOCAL_GL_FLOAT_MAT4 0x8B5C
+#define LOCAL_GL_FLOAT_MAT4_ARB 0x8B5C
+#define LOCAL_GL_FLOAT_MAT4x2 0x8B69
+#define LOCAL_GL_FLOAT_MAT4x2_NV 0x8B69
+#define LOCAL_GL_FLOAT_MAT4x3 0x8B6A
+#define LOCAL_GL_FLOAT_MAT4x3_NV 0x8B6A
+#define LOCAL_GL_FLOAT_R16_NV 0x8884
+#define LOCAL_GL_FLOAT_R32_NV 0x8885
+#define LOCAL_GL_FLOAT_RG16_NV 0x8886
+#define LOCAL_GL_FLOAT_RG32_NV 0x8887
+#define LOCAL_GL_FLOAT_RGB16_NV 0x8888
+#define LOCAL_GL_FLOAT_RGB32_NV 0x8889
+#define LOCAL_GL_FLOAT_RGBA16_NV 0x888A
+#define LOCAL_GL_FLOAT_RGBA32_NV 0x888B
+#define LOCAL_GL_FLOAT_RGBA_MODE_NV 0x888E
+#define LOCAL_GL_FLOAT_RGBA_NV 0x8883
+#define LOCAL_GL_FLOAT_RGB_NV 0x8882
+#define LOCAL_GL_FLOAT_RG_NV 0x8881
+#define LOCAL_GL_FLOAT_R_NV 0x8880
+#define LOCAL_GL_FLOAT_VEC2 0x8B50
+#define LOCAL_GL_FLOAT_VEC2_ARB 0x8B50
+#define LOCAL_GL_FLOAT_VEC3 0x8B51
+#define LOCAL_GL_FLOAT_VEC3_ARB 0x8B51
+#define LOCAL_GL_FLOAT_VEC4 0x8B52
+#define LOCAL_GL_FLOAT_VEC4_ARB 0x8B52
+#define LOCAL_GL_FOG 0x0B60
+#define LOCAL_GL_FOG_BIT 0x00000080
+#define LOCAL_GL_FOG_COLOR 0x0B66
+#define LOCAL_GL_FOG_COORD 0x8451
+#define LOCAL_GL_FOG_COORDINATE 0x8451
+#define LOCAL_GL_FOG_COORDINATE_ARRAY 0x8457
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_EXT 0x8457
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_LIST_IBM 103076
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_LIST_STRIDE_IBM 103086
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_POINTER_EXT 0x8456
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_STRIDE_EXT 0x8455
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define LOCAL_GL_FOG_COORDINATE_ARRAY_TYPE_EXT 0x8454
+#define LOCAL_GL_FOG_COORDINATE_EXT 0x8451
+#define LOCAL_GL_FOG_COORDINATE_SOURCE 0x8450
+#define LOCAL_GL_FOG_COORDINATE_SOURCE_EXT 0x8450
+#define LOCAL_GL_FOG_COORD_ARRAY 0x8457
+#define LOCAL_GL_FOG_COORD_ARRAY_ADDRESS_NV 0x8F28
+#define LOCAL_GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define LOCAL_GL_FOG_COORD_ARRAY_LENGTH_NV 0x8F32
+#define LOCAL_GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define LOCAL_GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define LOCAL_GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define LOCAL_GL_FOG_COORD_SRC 0x8450
+#define LOCAL_GL_FOG_DENSITY 0x0B62
+#define LOCAL_GL_FOG_DISTANCE_MODE_NV 0x855A
+#define LOCAL_GL_FOG_END 0x0B64
+#define LOCAL_GL_FOG_FUNC_POINTS_SGIS 0x812B
+#define LOCAL_GL_FOG_FUNC_SGIS 0x812A
+#define LOCAL_GL_FOG_HINT 0x0C54
+#define LOCAL_GL_FOG_INDEX 0x0B61
+#define LOCAL_GL_FOG_MODE 0x0B65
+#define LOCAL_GL_FOG_OFFSET_SGIX 0x8198
+#define LOCAL_GL_FOG_OFFSET_VALUE_SGIX 0x8199
+#define LOCAL_GL_FOG_SPECULAR_TEXTURE_WIN 0x80EC
+#define LOCAL_GL_FOG_START 0x0B63
+#define LOCAL_GL_FONT_ASCENDER_BIT_NV 0x00200000
+#define LOCAL_GL_FONT_DESCENDER_BIT_NV 0x00400000
+#define LOCAL_GL_FONT_GLYPHS_AVAILABLE_NV 0x9368
+#define LOCAL_GL_FONT_HAS_KERNING_BIT_NV 0x10000000
+#define LOCAL_GL_FONT_HEIGHT_BIT_NV 0x00800000
+#define LOCAL_GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define LOCAL_GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000
+#define LOCAL_GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000
+#define LOCAL_GL_FONT_TARGET_UNAVAILABLE_NV 0x9369
+#define LOCAL_GL_FONT_UNAVAILABLE_NV 0x936A
+#define LOCAL_GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define LOCAL_GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define LOCAL_GL_FONT_UNINTELLIGIBLE_NV 0x936B
+#define LOCAL_GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000
+#define LOCAL_GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000
+#define LOCAL_GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000
+#define LOCAL_GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000
+#define LOCAL_GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000
+#define LOCAL_GL_FORCE_BLUE_TO_ONE_NV 0x8860
+#define LOCAL_GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983
+#define LOCAL_GL_FORMAT_SUBSAMPLE_24_24_OML 0x8982
+#define LOCAL_GL_FOVEATION_ENABLE_BIT_QCOM 0x00000001
+#define LOCAL_GL_FOVEATION_SCALED_BIN_METHOD_BIT_QCOM 0x00000002
+#define LOCAL_GL_FOVEATION_SUBSAMPLED_LAYOUT_METHOD_BIT_QCOM 0x00000004
+#define LOCAL_GL_FRACTIONAL_EVEN 0x8E7C
+#define LOCAL_GL_FRACTIONAL_EVEN_EXT 0x8E7C
+#define LOCAL_GL_FRACTIONAL_EVEN_OES 0x8E7C
+#define LOCAL_GL_FRACTIONAL_ODD 0x8E7B
+#define LOCAL_GL_FRACTIONAL_ODD_EXT 0x8E7B
+#define LOCAL_GL_FRACTIONAL_ODD_OES 0x8E7B
+#define LOCAL_GL_FRAGMENTS_INSTRUMENT_COUNTERS_SGIX 0x8314
+#define LOCAL_GL_FRAGMENTS_INSTRUMENT_MAX_SGIX 0x8315
+#define LOCAL_GL_FRAGMENTS_INSTRUMENT_SGIX 0x8313
+#define LOCAL_GL_FRAGMENT_ALPHA_MODULATE_IMG 0x8C08
+#define LOCAL_GL_FRAGMENT_COLOR_EXT 0x834C
+#define LOCAL_GL_FRAGMENT_COLOR_MATERIAL_FACE_SGIX 0x8402
+#define LOCAL_GL_FRAGMENT_COLOR_MATERIAL_PARAMETER_SGIX 0x8403
+#define LOCAL_GL_FRAGMENT_COLOR_MATERIAL_SGIX 0x8401
+#define LOCAL_GL_FRAGMENT_COVERAGE_COLOR_NV 0x92DE
+#define LOCAL_GL_FRAGMENT_COVERAGE_TO_COLOR_NV 0x92DD
+#define LOCAL_GL_FRAGMENT_DEPTH 0x8452
+#define LOCAL_GL_FRAGMENT_DEPTH_EXT 0x8452
+#define LOCAL_GL_FRAGMENT_INPUT_NV 0x936D
+#define LOCAL_GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define LOCAL_GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D
+#define LOCAL_GL_FRAGMENT_LIGHT0_SGIX 0x840C
+#define LOCAL_GL_FRAGMENT_LIGHT1_SGIX 0x840D
+#define LOCAL_GL_FRAGMENT_LIGHT2_SGIX 0x840E
+#define LOCAL_GL_FRAGMENT_LIGHT3_SGIX 0x840F
+#define LOCAL_GL_FRAGMENT_LIGHT4_SGIX 0x8410
+#define LOCAL_GL_FRAGMENT_LIGHT5_SGIX 0x8411
+#define LOCAL_GL_FRAGMENT_LIGHT6_SGIX 0x8412
+#define LOCAL_GL_FRAGMENT_LIGHT7_SGIX 0x8413
+#define LOCAL_GL_FRAGMENT_LIGHTING_SGIX 0x8400
+#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
+#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
+#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
+#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
+#define LOCAL_GL_FRAGMENT_MATERIAL_EXT 0x8349
+#define LOCAL_GL_FRAGMENT_NORMAL_EXT 0x834A
+#define LOCAL_GL_FRAGMENT_PROGRAM_ARB 0x8804
+#define LOCAL_GL_FRAGMENT_PROGRAM_BINDING_NV 0x8873
+#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8BB3
+#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8BB2
+#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_MESA 0x8BB1
+#define LOCAL_GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
+#define LOCAL_GL_FRAGMENT_PROGRAM_NV 0x8870
+#define LOCAL_GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
+#define LOCAL_GL_FRAGMENT_PROGRAM_POSITION_MESA 0x8BB0
+#define LOCAL_GL_FRAGMENT_SHADER 0x8B30
+#define LOCAL_GL_FRAGMENT_SHADER_ARB 0x8B30
+#define LOCAL_GL_FRAGMENT_SHADER_ATI 0x8920
+#define LOCAL_GL_FRAGMENT_SHADER_BIT 0x00000002
+#define LOCAL_GL_FRAGMENT_SHADER_BIT_EXT 0x00000002
+#define LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B
+#define LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B
+#define LOCAL_GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52
+#define LOCAL_GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66
+#define LOCAL_GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4
+#define LOCAL_GL_FRAGMENT_SHADER_INVOCATIONS_ARB 0x82F4
+#define LOCAL_GL_FRAGMENT_SUBROUTINE 0x92EC
+#define LOCAL_GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define LOCAL_GL_FRAGMENT_TEXTURE 0x829F
+#define LOCAL_GL_FRAMEBUFFER 0x8D40
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB 0x8DA7
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
+#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG 0x913F
+#define LOCAL_GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define LOCAL_GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400
+#define LOCAL_GL_FRAMEBUFFER_BINDING 0x8CA6
+#define LOCAL_GL_FRAMEBUFFER_BINDING_ANGLE 0x8CA6
+#define LOCAL_GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
+#define LOCAL_GL_FRAMEBUFFER_BINDING_OES 0x8CA6
+#define LOCAL_GL_FRAMEBUFFER_BLEND 0x828B
+#define LOCAL_GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define LOCAL_GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
+#define LOCAL_GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT 0x8218
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define LOCAL_GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define LOCAL_GL_FRAMEBUFFER_EXT 0x8D40
+#define LOCAL_GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM 0x96A2
+#define LOCAL_GL_FRAMEBUFFER_FLIP_X_MESA 0x8BBC
+#define LOCAL_GL_FRAMEBUFFER_FLIP_Y_MESA 0x8BBB
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES 0x8CDB
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM 0x8BFF
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_EXT 0x9652
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB 0x8DA9
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG 0x913C
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES 0x8CDC
+#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
+#define LOCAL_GL_FRAMEBUFFER_OES 0x8D40
+#define LOCAL_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342
+#define LOCAL_GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define LOCAL_GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define LOCAL_GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define LOCAL_GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343
+#define LOCAL_GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+#define LOCAL_GL_FRAMEBUFFER_SRGB 0x8DB9
+#define LOCAL_GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
+#define LOCAL_GL_FRAMEBUFFER_SRGB_EXT 0x8DB9
+#define LOCAL_GL_FRAMEBUFFER_SWAP_XY_MESA 0x8BBD
+#define LOCAL_GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define LOCAL_GL_FRAMEBUFFER_UNDEFINED_OES 0x8219
+#define LOCAL_GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define LOCAL_GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
+#define LOCAL_GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD
+#define LOCAL_GL_FRAMEZOOM_FACTOR_SGIX 0x818C
+#define LOCAL_GL_FRAMEZOOM_SGIX 0x818B
+#define LOCAL_GL_FRAME_NV 0x8E26
+#define LOCAL_GL_FRONT 0x0404
+#define LOCAL_GL_FRONT_AND_BACK 0x0408
+#define LOCAL_GL_FRONT_FACE 0x0B46
+#define LOCAL_GL_FRONT_FACE_COMMAND_NV 0x0012
+#define LOCAL_GL_FRONT_LEFT 0x0400
+#define LOCAL_GL_FRONT_RIGHT 0x0401
+#define LOCAL_GL_FULL_RANGE_EXT 0x87E1
+#define LOCAL_GL_FULL_STIPPLE_HINT_PGI 0x1A219
+#define LOCAL_GL_FULL_SUPPORT 0x82B7
+#define LOCAL_GL_FUNC_ADD 0x8006
+#define LOCAL_GL_FUNC_ADD_EXT 0x8006
+#define LOCAL_GL_FUNC_ADD_OES 0x8006
+#define LOCAL_GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define LOCAL_GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B
+#define LOCAL_GL_FUNC_REVERSE_SUBTRACT_OES 0x800B
+#define LOCAL_GL_FUNC_SUBTRACT 0x800A
+#define LOCAL_GL_FUNC_SUBTRACT_EXT 0x800A
+#define LOCAL_GL_FUNC_SUBTRACT_OES 0x800A
+#define LOCAL_GL_GCCSO_SHADER_BINARY_FJ 0x9260
+#define LOCAL_GL_GENERATE_MIPMAP 0x8191
+#define LOCAL_GL_GENERATE_MIPMAP_HINT 0x8192
+#define LOCAL_GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
+#define LOCAL_GL_GENERATE_MIPMAP_SGIS 0x8191
+#define LOCAL_GL_GENERIC_ATTRIB_NV 0x8C7D
+#define LOCAL_GL_GEOMETRY_DEFORMATION_BIT_SGIX 0x00000002
+#define LOCAL_GL_GEOMETRY_DEFORMATION_SGIX 0x8194
+#define LOCAL_GL_GEOMETRY_INPUT_TYPE 0x8917
+#define LOCAL_GL_GEOMETRY_INPUT_TYPE_ARB 0x8DDB
+#define LOCAL_GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+#define LOCAL_GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917
+#define LOCAL_GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define LOCAL_GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918
+#define LOCAL_GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define LOCAL_GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916
+#define LOCAL_GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define LOCAL_GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define LOCAL_GL_GEOMETRY_OUTPUT_TYPE_ARB 0x8DDC
+#define LOCAL_GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+#define LOCAL_GL_GEOMETRY_PROGRAM_NV 0x8C26
+#define LOCAL_GL_GEOMETRY_PROGRAM_PARAMETER_BUFFER_NV 0x8DA3
+#define LOCAL_GL_GEOMETRY_SHADER 0x8DD9
+#define LOCAL_GL_GEOMETRY_SHADER_ARB 0x8DD9
+#define LOCAL_GL_GEOMETRY_SHADER_BIT 0x00000004
+#define LOCAL_GL_GEOMETRY_SHADER_BIT_EXT 0x00000004
+#define LOCAL_GL_GEOMETRY_SHADER_BIT_OES 0x00000004
+#define LOCAL_GL_GEOMETRY_SHADER_EXT 0x8DD9
+#define LOCAL_GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define LOCAL_GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F
+#define LOCAL_GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define LOCAL_GL_GEOMETRY_SHADER_OES 0x8DD9
+#define LOCAL_GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3
+#define LOCAL_GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB 0x82F3
+#define LOCAL_GL_GEOMETRY_SUBROUTINE 0x92EB
+#define LOCAL_GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define LOCAL_GL_GEOMETRY_TEXTURE 0x829E
+#define LOCAL_GL_GEOMETRY_VERTICES_OUT 0x8916
+#define LOCAL_GL_GEOMETRY_VERTICES_OUT_ARB 0x8DDA
+#define LOCAL_GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+#define LOCAL_GL_GEQUAL 0x0206
+#define LOCAL_GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define LOCAL_GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define LOCAL_GL_GLOBAL_ALPHA_FACTOR_SUN 0x81DA
+#define LOCAL_GL_GLOBAL_ALPHA_SUN 0x81D9
+#define LOCAL_GL_GLYPH_HAS_KERNING_BIT_NV 0x100
+#define LOCAL_GL_GLYPH_HEIGHT_BIT_NV 0x02
+#define LOCAL_GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define LOCAL_GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define LOCAL_GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define LOCAL_GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define LOCAL_GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define LOCAL_GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define LOCAL_GL_GLYPH_WIDTH_BIT_NV 0x01
+#define LOCAL_GL_GPU_ADDRESS_NV 0x8F34
+#define LOCAL_GL_GPU_DISJOINT_EXT 0x8FBB
+#define LOCAL_GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define LOCAL_GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define LOCAL_GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+#define LOCAL_GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define LOCAL_GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define LOCAL_GL_GPU_OPTIMIZED_QCOM 0x8FB2
+#define LOCAL_GL_GREATER 0x0204
+#define LOCAL_GL_GREEN 0x1904
+#define LOCAL_GL_GREEN_BIAS 0x0D19
+#define LOCAL_GL_GREEN_BITS 0x0D53
+#define LOCAL_GL_GREEN_BIT_ATI 0x00000002
+#define LOCAL_GL_GREEN_INTEGER 0x8D95
+#define LOCAL_GL_GREEN_INTEGER_EXT 0x8D95
+#define LOCAL_GL_GREEN_MAX_CLAMP_INGR 0x8565
+#define LOCAL_GL_GREEN_MIN_CLAMP_INGR 0x8561
+#define LOCAL_GL_GREEN_NV 0x1904
+#define LOCAL_GL_GREEN_SCALE 0x0D18
+#define LOCAL_GL_GS_PROGRAM_BINARY_MTK 0x9641
+#define LOCAL_GL_GS_SHADER_BINARY_MTK 0x9640
+#define LOCAL_GL_GUILTY_CONTEXT_RESET 0x8253
+#define LOCAL_GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define LOCAL_GL_GUILTY_CONTEXT_RESET_EXT 0x8253
+#define LOCAL_GL_GUILTY_CONTEXT_RESET_KHR 0x8253
+#define LOCAL_GL_HALF_APPLE 0x140B
+#define LOCAL_GL_HALF_BIAS_NEGATE_NV 0x853B
+#define LOCAL_GL_HALF_BIAS_NORMAL_NV 0x853A
+#define LOCAL_GL_HALF_BIT_ATI 0x00000008
+#define LOCAL_GL_HALF_FLOAT 0x140B
+#define LOCAL_GL_HALF_FLOAT_ARB 0x140B
+#define LOCAL_GL_HALF_FLOAT_NV 0x140B
+#define LOCAL_GL_HALF_FLOAT_OES 0x8D61
+#define LOCAL_GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B
+#define LOCAL_GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C
+#define LOCAL_GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594
+#define LOCAL_GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A
+#define LOCAL_GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589
+#define LOCAL_GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586
+#define LOCAL_GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587
+#define LOCAL_GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588
+#define LOCAL_GL_HARDLIGHT 0x929B
+#define LOCAL_GL_HARDLIGHT_KHR 0x929B
+#define LOCAL_GL_HARDLIGHT_NV 0x929B
+#define LOCAL_GL_HARDMIX_NV 0x92A9
+#define LOCAL_GL_HIGH_FLOAT 0x8DF2
+#define LOCAL_GL_HIGH_INT 0x8DF5
+#define LOCAL_GL_HILO16_NV 0x86F8
+#define LOCAL_GL_HILO8_NV 0x885E
+#define LOCAL_GL_HILO_NV 0x86F4
+#define LOCAL_GL_HINT_BIT 0x00008000
+#define LOCAL_GL_HISTOGRAM 0x8024
+#define LOCAL_GL_HISTOGRAM_ALPHA_SIZE 0x802B
+#define LOCAL_GL_HISTOGRAM_ALPHA_SIZE_EXT 0x802B
+#define LOCAL_GL_HISTOGRAM_BLUE_SIZE 0x802A
+#define LOCAL_GL_HISTOGRAM_BLUE_SIZE_EXT 0x802A
+#define LOCAL_GL_HISTOGRAM_EXT 0x8024
+#define LOCAL_GL_HISTOGRAM_FORMAT 0x8027
+#define LOCAL_GL_HISTOGRAM_FORMAT_EXT 0x8027
+#define LOCAL_GL_HISTOGRAM_GREEN_SIZE 0x8029
+#define LOCAL_GL_HISTOGRAM_GREEN_SIZE_EXT 0x8029
+#define LOCAL_GL_HISTOGRAM_LUMINANCE_SIZE 0x802C
+#define LOCAL_GL_HISTOGRAM_LUMINANCE_SIZE_EXT 0x802C
+#define LOCAL_GL_HISTOGRAM_RED_SIZE 0x8028
+#define LOCAL_GL_HISTOGRAM_RED_SIZE_EXT 0x8028
+#define LOCAL_GL_HISTOGRAM_SINK 0x802D
+#define LOCAL_GL_HISTOGRAM_SINK_EXT 0x802D
+#define LOCAL_GL_HISTOGRAM_WIDTH 0x8026
+#define LOCAL_GL_HISTOGRAM_WIDTH_EXT 0x8026
+#define LOCAL_GL_HI_BIAS_NV 0x8714
+#define LOCAL_GL_HI_SCALE_NV 0x870E
+#define LOCAL_GL_HORIZONTAL_LINE_TO_NV 0x06
+#define LOCAL_GL_HSL_COLOR 0x92AF
+#define LOCAL_GL_HSL_COLOR_KHR 0x92AF
+#define LOCAL_GL_HSL_COLOR_NV 0x92AF
+#define LOCAL_GL_HSL_HUE 0x92AD
+#define LOCAL_GL_HSL_HUE_KHR 0x92AD
+#define LOCAL_GL_HSL_HUE_NV 0x92AD
+#define LOCAL_GL_HSL_LUMINOSITY 0x92B0
+#define LOCAL_GL_HSL_LUMINOSITY_KHR 0x92B0
+#define LOCAL_GL_HSL_LUMINOSITY_NV 0x92B0
+#define LOCAL_GL_HSL_SATURATION 0x92AE
+#define LOCAL_GL_HSL_SATURATION_KHR 0x92AE
+#define LOCAL_GL_HSL_SATURATION_NV 0x92AE
+#define LOCAL_GL_IDENTITY_NV 0x862A
+#define LOCAL_GL_IGNORE_BORDER_HP 0x8150
+#define LOCAL_GL_IMAGE_1D 0x904C
+#define LOCAL_GL_IMAGE_1D_ARRAY 0x9052
+#define LOCAL_GL_IMAGE_1D_ARRAY_EXT 0x9052
+#define LOCAL_GL_IMAGE_1D_EXT 0x904C
+#define LOCAL_GL_IMAGE_2D 0x904D
+#define LOCAL_GL_IMAGE_2D_ARRAY 0x9053
+#define LOCAL_GL_IMAGE_2D_ARRAY_EXT 0x9053
+#define LOCAL_GL_IMAGE_2D_EXT 0x904D
+#define LOCAL_GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define LOCAL_GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define LOCAL_GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056
+#define LOCAL_GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055
+#define LOCAL_GL_IMAGE_2D_RECT 0x904F
+#define LOCAL_GL_IMAGE_2D_RECT_EXT 0x904F
+#define LOCAL_GL_IMAGE_3D 0x904E
+#define LOCAL_GL_IMAGE_3D_EXT 0x904E
+#define LOCAL_GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define LOCAL_GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E
+#define LOCAL_GL_IMAGE_BINDING_FORMAT 0x906E
+#define LOCAL_GL_IMAGE_BINDING_FORMAT_EXT 0x906E
+#define LOCAL_GL_IMAGE_BINDING_LAYER 0x8F3D
+#define LOCAL_GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define LOCAL_GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C
+#define LOCAL_GL_IMAGE_BINDING_LAYER_EXT 0x8F3D
+#define LOCAL_GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define LOCAL_GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B
+#define LOCAL_GL_IMAGE_BINDING_NAME 0x8F3A
+#define LOCAL_GL_IMAGE_BINDING_NAME_EXT 0x8F3A
+#define LOCAL_GL_IMAGE_BUFFER 0x9051
+#define LOCAL_GL_IMAGE_BUFFER_EXT 0x9051
+#define LOCAL_GL_IMAGE_BUFFER_OES 0x9051
+#define LOCAL_GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define LOCAL_GL_IMAGE_CLASS_11_11_10 0x82C2
+#define LOCAL_GL_IMAGE_CLASS_1_X_16 0x82BE
+#define LOCAL_GL_IMAGE_CLASS_1_X_32 0x82BB
+#define LOCAL_GL_IMAGE_CLASS_1_X_8 0x82C1
+#define LOCAL_GL_IMAGE_CLASS_2_X_16 0x82BD
+#define LOCAL_GL_IMAGE_CLASS_2_X_32 0x82BA
+#define LOCAL_GL_IMAGE_CLASS_2_X_8 0x82C0
+#define LOCAL_GL_IMAGE_CLASS_4_X_16 0x82BC
+#define LOCAL_GL_IMAGE_CLASS_4_X_32 0x82B9
+#define LOCAL_GL_IMAGE_CLASS_4_X_8 0x82BF
+#define LOCAL_GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define LOCAL_GL_IMAGE_CUBE 0x9050
+#define LOCAL_GL_IMAGE_CUBE_EXT 0x9050
+#define LOCAL_GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define LOCAL_GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054
+#define LOCAL_GL_IMAGE_CUBE_MAP_ARRAY_OES 0x9054
+#define LOCAL_GL_IMAGE_CUBIC_WEIGHT_HP 0x815E
+#define LOCAL_GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define LOCAL_GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define LOCAL_GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define LOCAL_GL_IMAGE_MAG_FILTER_HP 0x815C
+#define LOCAL_GL_IMAGE_MIN_FILTER_HP 0x815D
+#define LOCAL_GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define LOCAL_GL_IMAGE_PIXEL_TYPE 0x82AA
+#define LOCAL_GL_IMAGE_ROTATE_ANGLE_HP 0x8159
+#define LOCAL_GL_IMAGE_ROTATE_ORIGIN_X_HP 0x815A
+#define LOCAL_GL_IMAGE_ROTATE_ORIGIN_Y_HP 0x815B
+#define LOCAL_GL_IMAGE_SCALE_X_HP 0x8155
+#define LOCAL_GL_IMAGE_SCALE_Y_HP 0x8156
+#define LOCAL_GL_IMAGE_TEXEL_SIZE 0x82A7
+#define LOCAL_GL_IMAGE_TRANSFORM_2D_HP 0x8161
+#define LOCAL_GL_IMAGE_TRANSLATE_X_HP 0x8157
+#define LOCAL_GL_IMAGE_TRANSLATE_Y_HP 0x8158
+#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B
+#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A
+#define LOCAL_GL_INCLUSIVE_EXT 0x8F10
+#define LOCAL_GL_INCR 0x1E02
+#define LOCAL_GL_INCR_WRAP 0x8507
+#define LOCAL_GL_INCR_WRAP_EXT 0x8507
+#define LOCAL_GL_INCR_WRAP_OES 0x8507
+#define LOCAL_GL_INDEX 0x8222
+#define LOCAL_GL_INDEX_ARRAY 0x8077
+#define LOCAL_GL_INDEX_ARRAY_ADDRESS_NV 0x8F24
+#define LOCAL_GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define LOCAL_GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define LOCAL_GL_INDEX_ARRAY_COUNT_EXT 0x8087
+#define LOCAL_GL_INDEX_ARRAY_EXT 0x8077
+#define LOCAL_GL_INDEX_ARRAY_LENGTH_NV 0x8F2E
+#define LOCAL_GL_INDEX_ARRAY_LIST_IBM 103073
+#define LOCAL_GL_INDEX_ARRAY_LIST_STRIDE_IBM 103083
+#define LOCAL_GL_INDEX_ARRAY_POINTER 0x8091
+#define LOCAL_GL_INDEX_ARRAY_POINTER_EXT 0x8091
+#define LOCAL_GL_INDEX_ARRAY_STRIDE 0x8086
+#define LOCAL_GL_INDEX_ARRAY_STRIDE_EXT 0x8086
+#define LOCAL_GL_INDEX_ARRAY_TYPE 0x8085
+#define LOCAL_GL_INDEX_ARRAY_TYPE_EXT 0x8085
+#define LOCAL_GL_INDEX_BITS 0x0D51
+#define LOCAL_GL_INDEX_BIT_PGI 0x00080000
+#define LOCAL_GL_INDEX_CLEAR_VALUE 0x0C20
+#define LOCAL_GL_INDEX_LOGIC_OP 0x0BF1
+#define LOCAL_GL_INDEX_MATERIAL_EXT 0x81B8
+#define LOCAL_GL_INDEX_MATERIAL_FACE_EXT 0x81BA
+#define LOCAL_GL_INDEX_MATERIAL_PARAMETER_EXT 0x81B9
+#define LOCAL_GL_INDEX_MODE 0x0C30
+#define LOCAL_GL_INDEX_OFFSET 0x0D13
+#define LOCAL_GL_INDEX_SHIFT 0x0D12
+#define LOCAL_GL_INDEX_TEST_EXT 0x81B5
+#define LOCAL_GL_INDEX_TEST_FUNC_EXT 0x81B6
+#define LOCAL_GL_INDEX_TEST_REF_EXT 0x81B7
+#define LOCAL_GL_INDEX_WRITEMASK 0x0C21
+#define LOCAL_GL_INFO_LOG_LENGTH 0x8B84
+#define LOCAL_GL_INNOCENT_CONTEXT_RESET 0x8254
+#define LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define LOCAL_GL_INNOCENT_CONTEXT_RESET_EXT 0x8254
+#define LOCAL_GL_INNOCENT_CONTEXT_RESET_KHR 0x8254
+#define LOCAL_GL_INSTRUMENT_BUFFER_POINTER_SGIX 0x8180
+#define LOCAL_GL_INSTRUMENT_MEASUREMENTS_SGIX 0x8181
+#define LOCAL_GL_INT 0x1404
+#define LOCAL_GL_INT16_NV 0x8FE4
+#define LOCAL_GL_INT16_VEC2_NV 0x8FE5
+#define LOCAL_GL_INT16_VEC3_NV 0x8FE6
+#define LOCAL_GL_INT16_VEC4_NV 0x8FE7
+#define LOCAL_GL_INT64_ARB 0x140E
+#define LOCAL_GL_INT64_NV 0x140E
+#define LOCAL_GL_INT64_VEC2_ARB 0x8FE9
+#define LOCAL_GL_INT64_VEC2_NV 0x8FE9
+#define LOCAL_GL_INT64_VEC3_ARB 0x8FEA
+#define LOCAL_GL_INT64_VEC3_NV 0x8FEA
+#define LOCAL_GL_INT64_VEC4_ARB 0x8FEB
+#define LOCAL_GL_INT64_VEC4_NV 0x8FEB
+#define LOCAL_GL_INT8_NV 0x8FE0
+#define LOCAL_GL_INT8_VEC2_NV 0x8FE1
+#define LOCAL_GL_INT8_VEC3_NV 0x8FE2
+#define LOCAL_GL_INT8_VEC4_NV 0x8FE3
+#define LOCAL_GL_INTENSITY 0x8049
+#define LOCAL_GL_INTENSITY12 0x804C
+#define LOCAL_GL_INTENSITY12_EXT 0x804C
+#define LOCAL_GL_INTENSITY16 0x804D
+#define LOCAL_GL_INTENSITY16F_ARB 0x881D
+#define LOCAL_GL_INTENSITY16I_EXT 0x8D8B
+#define LOCAL_GL_INTENSITY16UI_EXT 0x8D79
+#define LOCAL_GL_INTENSITY16_EXT 0x804D
+#define LOCAL_GL_INTENSITY16_SNORM 0x901B
+#define LOCAL_GL_INTENSITY32F_ARB 0x8817
+#define LOCAL_GL_INTENSITY32I_EXT 0x8D85
+#define LOCAL_GL_INTENSITY32UI_EXT 0x8D73
+#define LOCAL_GL_INTENSITY4 0x804A
+#define LOCAL_GL_INTENSITY4_EXT 0x804A
+#define LOCAL_GL_INTENSITY8 0x804B
+#define LOCAL_GL_INTENSITY8I_EXT 0x8D91
+#define LOCAL_GL_INTENSITY8UI_EXT 0x8D7F
+#define LOCAL_GL_INTENSITY8_EXT 0x804B
+#define LOCAL_GL_INTENSITY8_SNORM 0x9017
+#define LOCAL_GL_INTENSITY_EXT 0x8049
+#define LOCAL_GL_INTENSITY_FLOAT16_APPLE 0x881D
+#define LOCAL_GL_INTENSITY_FLOAT16_ATI 0x881D
+#define LOCAL_GL_INTENSITY_FLOAT32_APPLE 0x8817
+#define LOCAL_GL_INTENSITY_FLOAT32_ATI 0x8817
+#define LOCAL_GL_INTENSITY_SNORM 0x9013
+#define LOCAL_GL_INTERLACE_OML 0x8980
+#define LOCAL_GL_INTERLACE_READ_INGR 0x8568
+#define LOCAL_GL_INTERLACE_READ_OML 0x8981
+#define LOCAL_GL_INTERLACE_SGIX 0x8094
+#define LOCAL_GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define LOCAL_GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C
+#define LOCAL_GL_INTERLEAVED_ATTRIBS_NV 0x8C8C
+#define LOCAL_GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define LOCAL_GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define LOCAL_GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define LOCAL_GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define LOCAL_GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define LOCAL_GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define LOCAL_GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define LOCAL_GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define LOCAL_GL_INTERNALFORMAT_PREFERRED 0x8270
+#define LOCAL_GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define LOCAL_GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define LOCAL_GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define LOCAL_GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define LOCAL_GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define LOCAL_GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define LOCAL_GL_INTERPOLATE 0x8575
+#define LOCAL_GL_INTERPOLATE_ARB 0x8575
+#define LOCAL_GL_INTERPOLATE_EXT 0x8575
+#define LOCAL_GL_INT_10_10_10_2_OES 0x8DF7
+#define LOCAL_GL_INT_2_10_10_10_REV 0x8D9F
+#define LOCAL_GL_INT_IMAGE_1D 0x9057
+#define LOCAL_GL_INT_IMAGE_1D_ARRAY 0x905D
+#define LOCAL_GL_INT_IMAGE_1D_ARRAY_EXT 0x905D
+#define LOCAL_GL_INT_IMAGE_1D_EXT 0x9057
+#define LOCAL_GL_INT_IMAGE_2D 0x9058
+#define LOCAL_GL_INT_IMAGE_2D_ARRAY 0x905E
+#define LOCAL_GL_INT_IMAGE_2D_ARRAY_EXT 0x905E
+#define LOCAL_GL_INT_IMAGE_2D_EXT 0x9058
+#define LOCAL_GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define LOCAL_GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define LOCAL_GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061
+#define LOCAL_GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060
+#define LOCAL_GL_INT_IMAGE_2D_RECT 0x905A
+#define LOCAL_GL_INT_IMAGE_2D_RECT_EXT 0x905A
+#define LOCAL_GL_INT_IMAGE_3D 0x9059
+#define LOCAL_GL_INT_IMAGE_3D_EXT 0x9059
+#define LOCAL_GL_INT_IMAGE_BUFFER 0x905C
+#define LOCAL_GL_INT_IMAGE_BUFFER_EXT 0x905C
+#define LOCAL_GL_INT_IMAGE_BUFFER_OES 0x905C
+#define LOCAL_GL_INT_IMAGE_CUBE 0x905B
+#define LOCAL_GL_INT_IMAGE_CUBE_EXT 0x905B
+#define LOCAL_GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define LOCAL_GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F
+#define LOCAL_GL_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x905F
+#define LOCAL_GL_INT_SAMPLER_1D 0x8DC9
+#define LOCAL_GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define LOCAL_GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE
+#define LOCAL_GL_INT_SAMPLER_1D_EXT 0x8DC9
+#define LOCAL_GL_INT_SAMPLER_2D 0x8DCA
+#define LOCAL_GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define LOCAL_GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF
+#define LOCAL_GL_INT_SAMPLER_2D_EXT 0x8DCA
+#define LOCAL_GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define LOCAL_GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define LOCAL_GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C
+#define LOCAL_GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define LOCAL_GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD
+#define LOCAL_GL_INT_SAMPLER_3D 0x8DCB
+#define LOCAL_GL_INT_SAMPLER_3D_EXT 0x8DCB
+#define LOCAL_GL_INT_SAMPLER_BUFFER 0x8DD0
+#define LOCAL_GL_INT_SAMPLER_BUFFER_AMD 0x9002
+#define LOCAL_GL_INT_SAMPLER_BUFFER_EXT 0x8DD0
+#define LOCAL_GL_INT_SAMPLER_BUFFER_OES 0x8DD0
+#define LOCAL_GL_INT_SAMPLER_CUBE 0x8DCC
+#define LOCAL_GL_INT_SAMPLER_CUBE_EXT 0x8DCC
+#define LOCAL_GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define LOCAL_GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
+#define LOCAL_GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E
+#define LOCAL_GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define LOCAL_GL_INT_SAMPLER_RENDERBUFFER_NV 0x8E57
+#define LOCAL_GL_INT_VEC2 0x8B53
+#define LOCAL_GL_INT_VEC2_ARB 0x8B53
+#define LOCAL_GL_INT_VEC3 0x8B54
+#define LOCAL_GL_INT_VEC3_ARB 0x8B54
+#define LOCAL_GL_INT_VEC4 0x8B55
+#define LOCAL_GL_INT_VEC4_ARB 0x8B55
+#define LOCAL_GL_INVALID_ENUM 0x0500
+#define LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
+#define LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506
+#define LOCAL_GL_INVALID_INDEX 0xFFFFFFFF
+#define LOCAL_GL_INVALID_OPERATION 0x0502
+#define LOCAL_GL_INVALID_VALUE 0x0501
+#define LOCAL_GL_INVARIANT_DATATYPE_EXT 0x87EB
+#define LOCAL_GL_INVARIANT_EXT 0x87C2
+#define LOCAL_GL_INVARIANT_VALUE_EXT 0x87EA
+#define LOCAL_GL_INVERSE_NV 0x862B
+#define LOCAL_GL_INVERSE_TRANSPOSE_NV 0x862D
+#define LOCAL_GL_INVERT 0x150A
+#define LOCAL_GL_INVERTED_SCREEN_W_REND 0x8491
+#define LOCAL_GL_INVERT_OVG_NV 0x92B4
+#define LOCAL_GL_INVERT_RGB_NV 0x92A3
+#define LOCAL_GL_IR_INSTRUMENT1_SGIX 0x817F
+#define LOCAL_GL_ISOLINES 0x8E7A
+#define LOCAL_GL_ISOLINES_EXT 0x8E7A
+#define LOCAL_GL_ISOLINES_OES 0x8E7A
+#define LOCAL_GL_IS_PER_PATCH 0x92E7
+#define LOCAL_GL_IS_PER_PATCH_EXT 0x92E7
+#define LOCAL_GL_IS_PER_PATCH_OES 0x92E7
+#define LOCAL_GL_IS_ROW_MAJOR 0x9300
+#define LOCAL_GL_ITALIC_BIT_NV 0x02
+#define LOCAL_GL_IUI_N3F_V2F_EXT 0x81AF
+#define LOCAL_GL_IUI_N3F_V3F_EXT 0x81B0
+#define LOCAL_GL_IUI_V2F_EXT 0x81AD
+#define LOCAL_GL_IUI_V3F_EXT 0x81AE
+#define LOCAL_GL_KEEP 0x1E00
+#define LOCAL_GL_LARGE_CCW_ARC_TO_NV 0x16
+#define LOCAL_GL_LARGE_CW_ARC_TO_NV 0x18
+#define LOCAL_GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define LOCAL_GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E
+#define LOCAL_GL_LAST_VERTEX_CONVENTION_OES 0x8E4E
+#define LOCAL_GL_LAST_VIDEO_CAPTURE_STATUS_NV 0x9027
+#define LOCAL_GL_LAYER_NV 0x8DAA
+#define LOCAL_GL_LAYER_PROVOKING_VERTEX 0x825E
+#define LOCAL_GL_LAYER_PROVOKING_VERTEX_EXT 0x825E
+#define LOCAL_GL_LAYER_PROVOKING_VERTEX_OES 0x825E
+#define LOCAL_GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E
+#define LOCAL_GL_LAYOUT_DEFAULT_INTEL 0
+#define LOCAL_GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531
+#define LOCAL_GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530
+#define LOCAL_GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F
+#define LOCAL_GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590
+#define LOCAL_GL_LAYOUT_GENERAL_EXT 0x958D
+#define LOCAL_GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2
+#define LOCAL_GL_LAYOUT_LINEAR_INTEL 1
+#define LOCAL_GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591
+#define LOCAL_GL_LAYOUT_TRANSFER_DST_EXT 0x9593
+#define LOCAL_GL_LAYOUT_TRANSFER_SRC_EXT 0x9592
+#define LOCAL_GL_LEFT 0x0406
+#define LOCAL_GL_LEQUAL 0x0203
+#define LOCAL_GL_LERP_ATI 0x8969
+#define LOCAL_GL_LESS 0x0201
+#define LOCAL_GL_LGPU_SEPARATE_STORAGE_BIT_NVX 0x0800
+#define LOCAL_GL_LIGHT0 0x4000
+#define LOCAL_GL_LIGHT1 0x4001
+#define LOCAL_GL_LIGHT2 0x4002
+#define LOCAL_GL_LIGHT3 0x4003
+#define LOCAL_GL_LIGHT4 0x4004
+#define LOCAL_GL_LIGHT5 0x4005
+#define LOCAL_GL_LIGHT6 0x4006
+#define LOCAL_GL_LIGHT7 0x4007
+#define LOCAL_GL_LIGHTEN 0x9298
+#define LOCAL_GL_LIGHTEN_KHR 0x9298
+#define LOCAL_GL_LIGHTEN_NV 0x9298
+#define LOCAL_GL_LIGHTING 0x0B50
+#define LOCAL_GL_LIGHTING_BIT 0x00000040
+#define LOCAL_GL_LIGHT_ENV_MODE_SGIX 0x8407
+#define LOCAL_GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define LOCAL_GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define LOCAL_GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define LOCAL_GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define LOCAL_GL_LIGHT_MODEL_SPECULAR_VECTOR_APPLE 0x85B0
+#define LOCAL_GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define LOCAL_GL_LINE 0x1B01
+#define LOCAL_GL_LINEAR 0x2601
+#define LOCAL_GL_LINEARBURN_NV 0x92A5
+#define LOCAL_GL_LINEARDODGE_NV 0x92A4
+#define LOCAL_GL_LINEARLIGHT_NV 0x92A7
+#define LOCAL_GL_LINEAR_ATTENUATION 0x1208
+#define LOCAL_GL_LINEAR_CLIPMAP_LINEAR_SGIX 0x8170
+#define LOCAL_GL_LINEAR_CLIPMAP_NEAREST_SGIX 0x844F
+#define LOCAL_GL_LINEAR_DETAIL_ALPHA_SGIS 0x8098
+#define LOCAL_GL_LINEAR_DETAIL_COLOR_SGIS 0x8099
+#define LOCAL_GL_LINEAR_DETAIL_SGIS 0x8097
+#define LOCAL_GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define LOCAL_GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define LOCAL_GL_LINEAR_SHARPEN_ALPHA_SGIS 0x80AE
+#define LOCAL_GL_LINEAR_SHARPEN_COLOR_SGIS 0x80AF
+#define LOCAL_GL_LINEAR_SHARPEN_SGIS 0x80AD
+#define LOCAL_GL_LINEAR_TILING_EXT 0x9585
+#define LOCAL_GL_LINES 0x0001
+#define LOCAL_GL_LINES_ADJACENCY 0x000A
+#define LOCAL_GL_LINES_ADJACENCY_ARB 0x000A
+#define LOCAL_GL_LINES_ADJACENCY_EXT 0x000A
+#define LOCAL_GL_LINES_ADJACENCY_OES 0x000A
+#define LOCAL_GL_LINE_BIT 0x00000004
+#define LOCAL_GL_LINE_LOOP 0x0002
+#define LOCAL_GL_LINE_NV 0x1B01
+#define LOCAL_GL_LINE_QUALITY_HINT_SGIX 0x835B
+#define LOCAL_GL_LINE_RESET_TOKEN 0x0707
+#define LOCAL_GL_LINE_SMOOTH 0x0B20
+#define LOCAL_GL_LINE_SMOOTH_HINT 0x0C52
+#define LOCAL_GL_LINE_STIPPLE 0x0B24
+#define LOCAL_GL_LINE_STIPPLE_PATTERN 0x0B25
+#define LOCAL_GL_LINE_STIPPLE_REPEAT 0x0B26
+#define LOCAL_GL_LINE_STRIP 0x0003
+#define LOCAL_GL_LINE_STRIP_ADJACENCY 0x000B
+#define LOCAL_GL_LINE_STRIP_ADJACENCY_ARB 0x000B
+#define LOCAL_GL_LINE_STRIP_ADJACENCY_EXT 0x000B
+#define LOCAL_GL_LINE_STRIP_ADJACENCY_OES 0x000B
+#define LOCAL_GL_LINE_TOKEN 0x0702
+#define LOCAL_GL_LINE_TO_NV 0x04
+#define LOCAL_GL_LINE_WIDTH 0x0B21
+#define LOCAL_GL_LINE_WIDTH_COMMAND_NV 0x000D
+#define LOCAL_GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define LOCAL_GL_LINE_WIDTH_RANGE 0x0B22
+#define LOCAL_GL_LINK_STATUS 0x8B82
+#define LOCAL_GL_LIST_BASE 0x0B32
+#define LOCAL_GL_LIST_BIT 0x00020000
+#define LOCAL_GL_LIST_INDEX 0x0B33
+#define LOCAL_GL_LIST_MODE 0x0B30
+#define LOCAL_GL_LIST_PRIORITY_SGIX 0x8182
+#define LOCAL_GL_LOAD 0x0101
+#define LOCAL_GL_LOCAL_CONSTANT_DATATYPE_EXT 0x87ED
+#define LOCAL_GL_LOCAL_CONSTANT_EXT 0x87C3
+#define LOCAL_GL_LOCAL_CONSTANT_VALUE_EXT 0x87EC
+#define LOCAL_GL_LOCAL_EXT 0x87C4
+#define LOCAL_GL_LOCATION 0x930E
+#define LOCAL_GL_LOCATION_COMPONENT 0x934A
+#define LOCAL_GL_LOCATION_INDEX 0x930F
+#define LOCAL_GL_LOCATION_INDEX_EXT 0x930F
+#define LOCAL_GL_LOGIC_OP 0x0BF1
+#define LOCAL_GL_LOGIC_OP_MODE 0x0BF0
+#define LOCAL_GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252
+#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252
+#define LOCAL_GL_LOWER_LEFT 0x8CA1
+#define LOCAL_GL_LOWER_LEFT_EXT 0x8CA1
+#define LOCAL_GL_LOW_FLOAT 0x8DF0
+#define LOCAL_GL_LOW_INT 0x8DF3
+#define LOCAL_GL_LO_BIAS_NV 0x8715
+#define LOCAL_GL_LO_SCALE_NV 0x870F
+#define LOCAL_GL_LUID_SIZE_EXT 8
+#define LOCAL_GL_LUMINANCE 0x1909
+#define LOCAL_GL_LUMINANCE12 0x8041
+#define LOCAL_GL_LUMINANCE12_ALPHA12 0x8047
+#define LOCAL_GL_LUMINANCE12_ALPHA12_EXT 0x8047
+#define LOCAL_GL_LUMINANCE12_ALPHA4 0x8046
+#define LOCAL_GL_LUMINANCE12_ALPHA4_EXT 0x8046
+#define LOCAL_GL_LUMINANCE12_EXT 0x8041
+#define LOCAL_GL_LUMINANCE16 0x8042
+#define LOCAL_GL_LUMINANCE16F_ARB 0x881E
+#define LOCAL_GL_LUMINANCE16F_EXT 0x881E
+#define LOCAL_GL_LUMINANCE16I_EXT 0x8D8C
+#define LOCAL_GL_LUMINANCE16UI_EXT 0x8D7A
+#define LOCAL_GL_LUMINANCE16_ALPHA16 0x8048
+#define LOCAL_GL_LUMINANCE16_ALPHA16_EXT 0x8048
+#define LOCAL_GL_LUMINANCE16_ALPHA16_SNORM 0x901A
+#define LOCAL_GL_LUMINANCE16_EXT 0x8042
+#define LOCAL_GL_LUMINANCE16_SNORM 0x9019
+#define LOCAL_GL_LUMINANCE32F_ARB 0x8818
+#define LOCAL_GL_LUMINANCE32F_EXT 0x8818
+#define LOCAL_GL_LUMINANCE32I_EXT 0x8D86
+#define LOCAL_GL_LUMINANCE32UI_EXT 0x8D74
+#define LOCAL_GL_LUMINANCE4 0x803F
+#define LOCAL_GL_LUMINANCE4_ALPHA4 0x8043
+#define LOCAL_GL_LUMINANCE4_ALPHA4_EXT 0x8043
+#define LOCAL_GL_LUMINANCE4_ALPHA4_OES 0x8043
+#define LOCAL_GL_LUMINANCE4_EXT 0x803F
+#define LOCAL_GL_LUMINANCE6_ALPHA2 0x8044
+#define LOCAL_GL_LUMINANCE6_ALPHA2_EXT 0x8044
+#define LOCAL_GL_LUMINANCE8 0x8040
+#define LOCAL_GL_LUMINANCE8I_EXT 0x8D92
+#define LOCAL_GL_LUMINANCE8UI_EXT 0x8D80
+#define LOCAL_GL_LUMINANCE8_ALPHA8 0x8045
+#define LOCAL_GL_LUMINANCE8_ALPHA8_EXT 0x8045
+#define LOCAL_GL_LUMINANCE8_ALPHA8_OES 0x8045
+#define LOCAL_GL_LUMINANCE8_ALPHA8_SNORM 0x9016
+#define LOCAL_GL_LUMINANCE8_EXT 0x8040
+#define LOCAL_GL_LUMINANCE8_OES 0x8040
+#define LOCAL_GL_LUMINANCE8_SNORM 0x9015
+#define LOCAL_GL_LUMINANCE_ALPHA 0x190A
+#define LOCAL_GL_LUMINANCE_ALPHA16F_ARB 0x881F
+#define LOCAL_GL_LUMINANCE_ALPHA16F_EXT 0x881F
+#define LOCAL_GL_LUMINANCE_ALPHA16I_EXT 0x8D8D
+#define LOCAL_GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B
+#define LOCAL_GL_LUMINANCE_ALPHA32F_ARB 0x8819
+#define LOCAL_GL_LUMINANCE_ALPHA32F_EXT 0x8819
+#define LOCAL_GL_LUMINANCE_ALPHA32I_EXT 0x8D87
+#define LOCAL_GL_LUMINANCE_ALPHA32UI_EXT 0x8D75
+#define LOCAL_GL_LUMINANCE_ALPHA8I_EXT 0x8D93
+#define LOCAL_GL_LUMINANCE_ALPHA8UI_EXT 0x8D81
+#define LOCAL_GL_LUMINANCE_ALPHA_FLOAT16_APPLE 0x881F
+#define LOCAL_GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F
+#define LOCAL_GL_LUMINANCE_ALPHA_FLOAT32_APPLE 0x8819
+#define LOCAL_GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819
+#define LOCAL_GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D
+#define LOCAL_GL_LUMINANCE_ALPHA_SNORM 0x9012
+#define LOCAL_GL_LUMINANCE_FLOAT16_APPLE 0x881E
+#define LOCAL_GL_LUMINANCE_FLOAT16_ATI 0x881E
+#define LOCAL_GL_LUMINANCE_FLOAT32_APPLE 0x8818
+#define LOCAL_GL_LUMINANCE_FLOAT32_ATI 0x8818
+#define LOCAL_GL_LUMINANCE_INTEGER_EXT 0x8D9C
+#define LOCAL_GL_LUMINANCE_SNORM 0x9011
+#define LOCAL_GL_MAD_ATI 0x8968
+#define LOCAL_GL_MAGNITUDE_BIAS_NV 0x8718
+#define LOCAL_GL_MAGNITUDE_SCALE_NV 0x8712
+#define LOCAL_GL_MAJOR_VERSION 0x821B
+#define LOCAL_GL_MALI_PROGRAM_BINARY_ARM 0x8F61
+#define LOCAL_GL_MALI_SHADER_BINARY_ARM 0x8F60
+#define LOCAL_GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define LOCAL_GL_MAP1_BINORMAL_EXT 0x8446
+#define LOCAL_GL_MAP1_COLOR_4 0x0D90
+#define LOCAL_GL_MAP1_GRID_DOMAIN 0x0DD0
+#define LOCAL_GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define LOCAL_GL_MAP1_INDEX 0x0D91
+#define LOCAL_GL_MAP1_NORMAL 0x0D92
+#define LOCAL_GL_MAP1_TANGENT_EXT 0x8444
+#define LOCAL_GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define LOCAL_GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define LOCAL_GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define LOCAL_GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define LOCAL_GL_MAP1_VERTEX_3 0x0D97
+#define LOCAL_GL_MAP1_VERTEX_4 0x0D98
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB0_4_NV 0x8660
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB10_4_NV 0x866A
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB11_4_NV 0x866B
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB12_4_NV 0x866C
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB13_4_NV 0x866D
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB14_4_NV 0x866E
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB15_4_NV 0x866F
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB1_4_NV 0x8661
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB2_4_NV 0x8662
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB3_4_NV 0x8663
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB4_4_NV 0x8664
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB5_4_NV 0x8665
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB6_4_NV 0x8666
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB7_4_NV 0x8667
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB8_4_NV 0x8668
+#define LOCAL_GL_MAP1_VERTEX_ATTRIB9_4_NV 0x8669
+#define LOCAL_GL_MAP2_BINORMAL_EXT 0x8447
+#define LOCAL_GL_MAP2_COLOR_4 0x0DB0
+#define LOCAL_GL_MAP2_GRID_DOMAIN 0x0DD2
+#define LOCAL_GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define LOCAL_GL_MAP2_INDEX 0x0DB1
+#define LOCAL_GL_MAP2_NORMAL 0x0DB2
+#define LOCAL_GL_MAP2_TANGENT_EXT 0x8445
+#define LOCAL_GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define LOCAL_GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define LOCAL_GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define LOCAL_GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define LOCAL_GL_MAP2_VERTEX_3 0x0DB7
+#define LOCAL_GL_MAP2_VERTEX_4 0x0DB8
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB0_4_NV 0x8670
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB10_4_NV 0x867A
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB11_4_NV 0x867B
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB12_4_NV 0x867C
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB13_4_NV 0x867D
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB14_4_NV 0x867E
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB15_4_NV 0x867F
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB1_4_NV 0x8671
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB2_4_NV 0x8672
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB3_4_NV 0x8673
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB4_4_NV 0x8674
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB5_4_NV 0x8675
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB6_4_NV 0x8676
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB7_4_NV 0x8677
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB8_4_NV 0x8678
+#define LOCAL_GL_MAP2_VERTEX_ATTRIB9_4_NV 0x8679
+#define LOCAL_GL_MAP_ATTRIB_U_ORDER_NV 0x86C3
+#define LOCAL_GL_MAP_ATTRIB_V_ORDER_NV 0x86C4
+#define LOCAL_GL_MAP_COHERENT_BIT 0x0080
+#define LOCAL_GL_MAP_COHERENT_BIT_EXT 0x0080
+#define LOCAL_GL_MAP_COLOR 0x0D10
+#define LOCAL_GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define LOCAL_GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010
+#define LOCAL_GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define LOCAL_GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008
+#define LOCAL_GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define LOCAL_GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004
+#define LOCAL_GL_MAP_PERSISTENT_BIT 0x0040
+#define LOCAL_GL_MAP_PERSISTENT_BIT_EXT 0x0040
+#define LOCAL_GL_MAP_READ_BIT 0x0001
+#define LOCAL_GL_MAP_READ_BIT_EXT 0x0001
+#define LOCAL_GL_MAP_STENCIL 0x0D11
+#define LOCAL_GL_MAP_TESSELLATION_NV 0x86C2
+#define LOCAL_GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define LOCAL_GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020
+#define LOCAL_GL_MAP_WRITE_BIT 0x0002
+#define LOCAL_GL_MAP_WRITE_BIT_EXT 0x0002
+#define LOCAL_GL_MATERIAL_SIDE_HINT_PGI 0x1A22C
+#define LOCAL_GL_MATRIX0_ARB 0x88C0
+#define LOCAL_GL_MATRIX0_NV 0x8630
+#define LOCAL_GL_MATRIX10_ARB 0x88CA
+#define LOCAL_GL_MATRIX11_ARB 0x88CB
+#define LOCAL_GL_MATRIX12_ARB 0x88CC
+#define LOCAL_GL_MATRIX13_ARB 0x88CD
+#define LOCAL_GL_MATRIX14_ARB 0x88CE
+#define LOCAL_GL_MATRIX15_ARB 0x88CF
+#define LOCAL_GL_MATRIX16_ARB 0x88D0
+#define LOCAL_GL_MATRIX17_ARB 0x88D1
+#define LOCAL_GL_MATRIX18_ARB 0x88D2
+#define LOCAL_GL_MATRIX19_ARB 0x88D3
+#define LOCAL_GL_MATRIX1_ARB 0x88C1
+#define LOCAL_GL_MATRIX1_NV 0x8631
+#define LOCAL_GL_MATRIX20_ARB 0x88D4
+#define LOCAL_GL_MATRIX21_ARB 0x88D5
+#define LOCAL_GL_MATRIX22_ARB 0x88D6
+#define LOCAL_GL_MATRIX23_ARB 0x88D7
+#define LOCAL_GL_MATRIX24_ARB 0x88D8
+#define LOCAL_GL_MATRIX25_ARB 0x88D9
+#define LOCAL_GL_MATRIX26_ARB 0x88DA
+#define LOCAL_GL_MATRIX27_ARB 0x88DB
+#define LOCAL_GL_MATRIX28_ARB 0x88DC
+#define LOCAL_GL_MATRIX29_ARB 0x88DD
+#define LOCAL_GL_MATRIX2_ARB 0x88C2
+#define LOCAL_GL_MATRIX2_NV 0x8632
+#define LOCAL_GL_MATRIX30_ARB 0x88DE
+#define LOCAL_GL_MATRIX31_ARB 0x88DF
+#define LOCAL_GL_MATRIX3_ARB 0x88C3
+#define LOCAL_GL_MATRIX3_NV 0x8633
+#define LOCAL_GL_MATRIX4_ARB 0x88C4
+#define LOCAL_GL_MATRIX4_NV 0x8634
+#define LOCAL_GL_MATRIX5_ARB 0x88C5
+#define LOCAL_GL_MATRIX5_NV 0x8635
+#define LOCAL_GL_MATRIX6_ARB 0x88C6
+#define LOCAL_GL_MATRIX6_NV 0x8636
+#define LOCAL_GL_MATRIX7_ARB 0x88C7
+#define LOCAL_GL_MATRIX7_NV 0x8637
+#define LOCAL_GL_MATRIX8_ARB 0x88C8
+#define LOCAL_GL_MATRIX9_ARB 0x88C9
+#define LOCAL_GL_MATRIX_EXT 0x87C0
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_ARB 0x8844
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 0x8B9E
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_OES 0x8844
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_POINTER_ARB 0x8849
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_POINTER_OES 0x8849
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_SIZE_ARB 0x8846
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_SIZE_OES 0x8846
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_STRIDE_ARB 0x8848
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_STRIDE_OES 0x8848
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_TYPE_ARB 0x8847
+#define LOCAL_GL_MATRIX_INDEX_ARRAY_TYPE_OES 0x8847
+#define LOCAL_GL_MATRIX_MODE 0x0BA0
+#define LOCAL_GL_MATRIX_PALETTE_ARB 0x8840
+#define LOCAL_GL_MATRIX_PALETTE_OES 0x8840
+#define LOCAL_GL_MATRIX_STRIDE 0x92FF
+#define LOCAL_GL_MAT_AMBIENT_AND_DIFFUSE_BIT_PGI 0x00200000
+#define LOCAL_GL_MAT_AMBIENT_BIT_PGI 0x00100000
+#define LOCAL_GL_MAT_COLOR_INDEXES_BIT_PGI 0x01000000
+#define LOCAL_GL_MAT_DIFFUSE_BIT_PGI 0x00400000
+#define LOCAL_GL_MAT_EMISSION_BIT_PGI 0x00800000
+#define LOCAL_GL_MAT_SHININESS_BIT_PGI 0x02000000
+#define LOCAL_GL_MAT_SPECULAR_BIT_PGI 0x04000000
+#define LOCAL_GL_MAX 0x8008
+#define LOCAL_GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define LOCAL_GL_MAX_3D_TEXTURE_SIZE_EXT 0x8073
+#define LOCAL_GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
+#define LOCAL_GL_MAX_4D_TEXTURE_SIZE_SGIS 0x8138
+#define LOCAL_GL_MAX_ACTIVE_LIGHTS_SGIX 0x8405
+#define LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF
+#define LOCAL_GL_MAX_ASYNC_DRAW_PIXELS_SGIX 0x8360
+#define LOCAL_GL_MAX_ASYNC_HISTOGRAM_SGIX 0x832D
+#define LOCAL_GL_MAX_ASYNC_READ_PIXELS_SGIX 0x8361
+#define LOCAL_GL_MAX_ASYNC_TEX_IMAGE_SGIX 0x835F
+#define LOCAL_GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define LOCAL_GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define LOCAL_GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define LOCAL_GL_MAX_BINDABLE_UNIFORM_SIZE_EXT 0x8DED
+#define LOCAL_GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define LOCAL_GL_MAX_CLIPMAP_DEPTH_SGIX 0x8177
+#define LOCAL_GL_MAX_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8178
+#define LOCAL_GL_MAX_CLIP_DISTANCES 0x0D32
+#define LOCAL_GL_MAX_CLIP_DISTANCES_APPLE 0x0D32
+#define LOCAL_GL_MAX_CLIP_DISTANCES_EXT 0x0D32
+#define LOCAL_GL_MAX_CLIP_PLANES 0x0D32
+#define LOCAL_GL_MAX_CLIP_PLANES_IMG 0x0D32
+#define LOCAL_GL_MAX_COARSE_FRAGMENT_SAMPLES_NV 0x955F
+#define LOCAL_GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define LOCAL_GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
+#define LOCAL_GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF
+#define LOCAL_GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3
+#define LOCAL_GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4
+#define LOCAL_GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3
+#define LOCAL_GL_MAX_COLOR_MATRIX_STACK_DEPTH_SGI 0x80B3
+#define LOCAL_GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define LOCAL_GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define LOCAL_GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define LOCAL_GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define LOCAL_GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
+#define LOCAL_GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define LOCAL_GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define LOCAL_GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define LOCAL_GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32
+#define LOCAL_GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define LOCAL_GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
+#define LOCAL_GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV 0x8E67
+#define LOCAL_GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define LOCAL_GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define LOCAL_GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV 0x8E6F
+#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E
+#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F
+#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
+#define LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define LOCAL_GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define LOCAL_GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define LOCAL_GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB 0x90EB
+#define LOCAL_GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB 0x91BF
+#define LOCAL_GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define LOCAL_GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define LOCAL_GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define LOCAL_GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define LOCAL_GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define LOCAL_GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define LOCAL_GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB 0x9344
+#define LOCAL_GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB 0x9345
+#define LOCAL_GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define LOCAL_GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define LOCAL_GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define LOCAL_GL_MAX_CONVOLUTION_HEIGHT 0x801B
+#define LOCAL_GL_MAX_CONVOLUTION_HEIGHT_EXT 0x801B
+#define LOCAL_GL_MAX_CONVOLUTION_WIDTH 0x801A
+#define LOCAL_GL_MAX_CONVOLUTION_WIDTH_EXT 0x801A
+#define LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
+#define LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE_EXT 0x851C
+#define LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES 0x851C
+#define LOCAL_GL_MAX_CULL_DISTANCES 0x82F9
+#define LOCAL_GL_MAX_CULL_DISTANCES_EXT 0x82F9
+#define LOCAL_GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define LOCAL_GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C
+#define LOCAL_GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define LOCAL_GL_MAX_DEBUG_LOGGED_MESSAGES_AMD 0x9144
+#define LOCAL_GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144
+#define LOCAL_GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144
+#define LOCAL_GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define LOCAL_GL_MAX_DEBUG_MESSAGE_LENGTH_AMD 0x9143
+#define LOCAL_GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143
+#define LOCAL_GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143
+#define LOCAL_GL_MAX_DEEP_3D_TEXTURE_DEPTH_NV 0x90D1
+#define LOCAL_GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV 0x90D0
+#define LOCAL_GL_MAX_DEFORMATION_ORDER_SGIX 0x8197
+#define LOCAL_GL_MAX_DEPTH 0x8280
+#define LOCAL_GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5
+#define LOCAL_GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define LOCAL_GL_MAX_DETACHED_BUFFERS_NV 0x95AD
+#define LOCAL_GL_MAX_DETACHED_TEXTURES_NV 0x95AC
+#define LOCAL_GL_MAX_DRAW_BUFFERS 0x8824
+#define LOCAL_GL_MAX_DRAW_BUFFERS_ARB 0x8824
+#define LOCAL_GL_MAX_DRAW_BUFFERS_ATI 0x8824
+#define LOCAL_GL_MAX_DRAW_BUFFERS_EXT 0x8824
+#define LOCAL_GL_MAX_DRAW_BUFFERS_NV 0x8824
+#define LOCAL_GL_MAX_DRAW_MESH_TASKS_COUNT_NV 0x953D
+#define LOCAL_GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define LOCAL_GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+#define LOCAL_GL_MAX_ELEMENTS_INDICES 0x80E9
+#define LOCAL_GL_MAX_ELEMENTS_INDICES_EXT 0x80E9
+#define LOCAL_GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define LOCAL_GL_MAX_ELEMENTS_VERTICES_EXT 0x80E8
+#define LOCAL_GL_MAX_ELEMENT_INDEX 0x8D6B
+#define LOCAL_GL_MAX_EVAL_ORDER 0x0D30
+#define LOCAL_GL_MAX_EXT 0x8008
+#define LOCAL_GL_MAX_FOG_FUNC_POINTS_SGIS 0x812C
+#define LOCAL_GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define LOCAL_GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define LOCAL_GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT 0x8DE3
+#define LOCAL_GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define LOCAL_GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define LOCAL_GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5C
+#define LOCAL_GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C
+#define LOCAL_GL_MAX_FRAGMENT_LIGHTS_SGIX 0x8404
+#define LOCAL_GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV 0x8868
+#define LOCAL_GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49
+#define LOCAL_GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define LOCAL_GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define LOCAL_GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define LOCAL_GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317
+#define LOCAL_GL_MAX_FRAMEBUFFER_LAYERS_OES 0x9317
+#define LOCAL_GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define LOCAL_GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define LOCAL_GL_MAX_FRAMEZOOM_FACTOR_SGIX 0x818D
+#define LOCAL_GL_MAX_GENERAL_COMBINERS_NV 0x854D
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF
+#define LOCAL_GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define LOCAL_GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4
+#define LOCAL_GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define LOCAL_GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD
+#define LOCAL_GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define LOCAL_GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define LOCAL_GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123
+#define LOCAL_GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB 0x8DE0
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define LOCAL_GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV 0x8E5A
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7
+#define LOCAL_GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define LOCAL_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define LOCAL_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB 0x8C29
+#define LOCAL_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+#define LOCAL_GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define LOCAL_GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define LOCAL_GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB 0x8DE1
+#define LOCAL_GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+#define LOCAL_GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB 0x8DDF
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+#define LOCAL_GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define LOCAL_GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB 0x8DDD
+#define LOCAL_GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+#define LOCAL_GL_MAX_HEIGHT 0x827F
+#define LOCAL_GL_MAX_IMAGE_SAMPLES 0x906D
+#define LOCAL_GL_MAX_IMAGE_SAMPLES_EXT 0x906D
+#define LOCAL_GL_MAX_IMAGE_UNITS 0x8F38
+#define LOCAL_GL_MAX_IMAGE_UNITS_EXT 0x8F38
+#define LOCAL_GL_MAX_INTEGER_SAMPLES 0x9110
+#define LOCAL_GL_MAX_LABEL_LENGTH 0x82E8
+#define LOCAL_GL_MAX_LABEL_LENGTH_KHR 0x82E8
+#define LOCAL_GL_MAX_LAYERS 0x8281
+#define LOCAL_GL_MAX_LGPU_GPUS_NVX 0x92BA
+#define LOCAL_GL_MAX_LIGHTS 0x0D31
+#define LOCAL_GL_MAX_LIST_NESTING 0x0B31
+#define LOCAL_GL_MAX_MAP_TESSELLATION_NV 0x86D6
+#define LOCAL_GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB 0x8841
+#define LOCAL_GL_MAX_MESH_ATOMIC_COUNTERS_NV 0x8E65
+#define LOCAL_GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV 0x8E64
+#define LOCAL_GL_MAX_MESH_IMAGE_UNIFORMS_NV 0x8E62
+#define LOCAL_GL_MAX_MESH_OUTPUT_PRIMITIVES_NV 0x9539
+#define LOCAL_GL_MAX_MESH_OUTPUT_VERTICES_NV 0x9538
+#define LOCAL_GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV 0x8E66
+#define LOCAL_GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV 0x8E61
+#define LOCAL_GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV 0x9536
+#define LOCAL_GL_MAX_MESH_UNIFORM_BLOCKS_NV 0x8E60
+#define LOCAL_GL_MAX_MESH_UNIFORM_COMPONENTS_NV 0x8E63
+#define LOCAL_GL_MAX_MESH_VIEWS_NV 0x9557
+#define LOCAL_GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV 0x95A2
+#define LOCAL_GL_MAX_MESH_WORK_GROUP_SIZE_NV 0x953B
+#define LOCAL_GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define LOCAL_GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
+#define LOCAL_GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2
+#define LOCAL_GL_MAX_NAME_LENGTH 0x92F6
+#define LOCAL_GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define LOCAL_GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define LOCAL_GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
+#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
+#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
+#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
+#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
+#define LOCAL_GL_MAX_PALETTE_MATRICES_ARB 0x8842
+#define LOCAL_GL_MAX_PALETTE_MATRICES_OES 0x8842
+#define LOCAL_GL_MAX_PATCH_VERTICES 0x8E7D
+#define LOCAL_GL_MAX_PATCH_VERTICES_EXT 0x8E7D
+#define LOCAL_GL_MAX_PATCH_VERTICES_OES 0x8E7D
+#define LOCAL_GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define LOCAL_GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8337
+#define LOCAL_GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
+#define LOCAL_GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
+#define LOCAL_GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
+#define LOCAL_GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
+#define LOCAL_GL_MAX_PROGRAM_ATTRIB_COMPONENTS_NV 0x8908
+#define LOCAL_GL_MAX_PROGRAM_CALL_DEPTH_NV 0x88F5
+#define LOCAL_GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
+#define LOCAL_GL_MAX_PROGRAM_EXEC_INSTRUCTIONS_NV 0x88F4
+#define LOCAL_GL_MAX_PROGRAM_GENERIC_ATTRIBS_NV 0x8DA5
+#define LOCAL_GL_MAX_PROGRAM_GENERIC_RESULTS_NV 0x8DA6
+#define LOCAL_GL_MAX_PROGRAM_IF_DEPTH_NV 0x88F6
+#define LOCAL_GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
+#define LOCAL_GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
+#define LOCAL_GL_MAX_PROGRAM_LOOP_COUNT_NV 0x88F8
+#define LOCAL_GL_MAX_PROGRAM_LOOP_DEPTH_NV 0x88F7
+#define LOCAL_GL_MAX_PROGRAM_MATRICES_ARB 0x862F
+#define LOCAL_GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
+#define LOCAL_GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
+#define LOCAL_GL_MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27
+#define LOCAL_GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
+#define LOCAL_GL_MAX_PROGRAM_PARAMETER_BUFFER_BINDINGS_NV 0x8DA0
+#define LOCAL_GL_MAX_PROGRAM_PARAMETER_BUFFER_SIZE_NV 0x8DA1
+#define LOCAL_GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8
+#define LOCAL_GL_MAX_PROGRAM_RESULT_COMPONENTS_NV 0x8909
+#define LOCAL_GL_MAX_PROGRAM_SUBROUTINE_NUM_NV 0x8F45
+#define LOCAL_GL_MAX_PROGRAM_SUBROUTINE_PARAMETERS_NV 0x8F44
+#define LOCAL_GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
+#define LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905
+#define LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET_NV 0x8905
+#define LOCAL_GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS_ARB 0x8F9F
+#define LOCAL_GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define LOCAL_GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5F
+#define LOCAL_GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5F
+#define LOCAL_GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
+#define LOCAL_GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
+#define LOCAL_GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28
+#define LOCAL_GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define LOCAL_GL_MAX_RASTER_SAMPLES_EXT 0x9329
+#define LOCAL_GL_MAX_RATIONAL_EVAL_ORDER_NV 0x86D7
+#define LOCAL_GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define LOCAL_GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
+#define LOCAL_GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8
+#define LOCAL_GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define LOCAL_GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
+#define LOCAL_GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8
+#define LOCAL_GL_MAX_SAMPLES 0x8D57
+#define LOCAL_GL_MAX_SAMPLES_ANGLE 0x8D57
+#define LOCAL_GL_MAX_SAMPLES_APPLE 0x8D57
+#define LOCAL_GL_MAX_SAMPLES_EXT 0x8D57
+#define LOCAL_GL_MAX_SAMPLES_IMG 0x9135
+#define LOCAL_GL_MAX_SAMPLES_NV 0x8D57
+#define LOCAL_GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define LOCAL_GL_MAX_SAMPLE_MASK_WORDS_NV 0x8E59
+#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111
+#define LOCAL_GL_MAX_SHADER_BUFFER_ADDRESS_NV 0x8F35
+#define LOCAL_GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT 0x9650
+#define LOCAL_GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT 0x9651
+#define LOCAL_GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0
+#define LOCAL_GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define LOCAL_GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
+#define LOCAL_GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67
+#define LOCAL_GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define LOCAL_GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define LOCAL_GL_MAX_SHADER_SUBSAMPLED_IMAGE_UNITS_QCOM 0x8FA1
+#define LOCAL_GL_MAX_SHININESS_NV 0x8504
+#define LOCAL_GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD 0x9199
+#define LOCAL_GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199
+#define LOCAL_GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define LOCAL_GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS 0x919A
+#define LOCAL_GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A
+#define LOCAL_GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define LOCAL_GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198
+#define LOCAL_GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198
+#define LOCAL_GL_MAX_SPARSE_TEXTURE_SIZE_EXT 0x9198
+#define LOCAL_GL_MAX_SPOT_EXPONENT_NV 0x8505
+#define LOCAL_GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+#define LOCAL_GL_MAX_SUBROUTINES 0x8DE7
+#define LOCAL_GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define LOCAL_GL_MAX_TASK_ATOMIC_COUNTERS_NV 0x8E6D
+#define LOCAL_GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV 0x8E6C
+#define LOCAL_GL_MAX_TASK_IMAGE_UNIFORMS_NV 0x8E6A
+#define LOCAL_GL_MAX_TASK_OUTPUT_COUNT_NV 0x953A
+#define LOCAL_GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV 0x8E6E
+#define LOCAL_GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV 0x8E69
+#define LOCAL_GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV 0x9537
+#define LOCAL_GL_MAX_TASK_UNIFORM_BLOCKS_NV 0x8E68
+#define LOCAL_GL_MAX_TASK_UNIFORM_COMPONENTS_NV 0x8E6B
+#define LOCAL_GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV 0x95A3
+#define LOCAL_GL_MAX_TASK_WORK_GROUP_SIZE_NV 0x953C
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD
+#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define LOCAL_GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define LOCAL_GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB
+#define LOCAL_GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define LOCAL_GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define LOCAL_GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C
+#define LOCAL_GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define LOCAL_GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define LOCAL_GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83
+#define LOCAL_GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define LOCAL_GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define LOCAL_GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8
+#define LOCAL_GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define LOCAL_GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define LOCAL_GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81
+#define LOCAL_GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define LOCAL_GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define LOCAL_GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85
+#define LOCAL_GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F
+#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE
+#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define LOCAL_GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define LOCAL_GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC
+#define LOCAL_GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define LOCAL_GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define LOCAL_GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D
+#define LOCAL_GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define LOCAL_GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define LOCAL_GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86
+#define LOCAL_GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define LOCAL_GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define LOCAL_GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9
+#define LOCAL_GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define LOCAL_GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define LOCAL_GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82
+#define LOCAL_GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80
+#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define LOCAL_GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define LOCAL_GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E
+#define LOCAL_GL_MAX_TESS_GEN_LEVEL_OES 0x8E7E
+#define LOCAL_GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define LOCAL_GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84
+#define LOCAL_GL_MAX_TESS_PATCH_COMPONENTS_OES 0x8E84
+#define LOCAL_GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define LOCAL_GL_MAX_TEXTURE_BUFFER_SIZE_ARB 0x8C2B
+#define LOCAL_GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B
+#define LOCAL_GL_MAX_TEXTURE_BUFFER_SIZE_OES 0x8C2B
+#define LOCAL_GL_MAX_TEXTURE_COORDS 0x8871
+#define LOCAL_GL_MAX_TEXTURE_COORDS_ARB 0x8871
+#define LOCAL_GL_MAX_TEXTURE_COORDS_NV 0x8871
+#define LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
+#define LOCAL_GL_MAX_TEXTURE_IMAGE_UNITS_NV 0x8872
+#define LOCAL_GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define LOCAL_GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
+#define LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
+#define LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
+#define LOCAL_GL_MAX_TEXTURE_SIZE 0x0D33
+#define LOCAL_GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define LOCAL_GL_MAX_TEXTURE_UNITS 0x84E2
+#define LOCAL_GL_MAX_TEXTURE_UNITS_ARB 0x84E2
+#define LOCAL_GL_MAX_TIMELINE_SEMAPHORE_VALUE_DIFFERENCE_NV 0x95B6
+#define LOCAL_GL_MAX_TRACK_MATRICES_NV 0x862F
+#define LOCAL_GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
+#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
+#define LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define LOCAL_GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define LOCAL_GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define LOCAL_GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+#define LOCAL_GL_MAX_VARYING_FLOATS 0x8B4B
+#define LOCAL_GL_MAX_VARYING_FLOATS_ARB 0x8B4B
+#define LOCAL_GL_MAX_VARYING_VECTORS 0x8DFC
+#define LOCAL_GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV 0x8520
+#define LOCAL_GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define LOCAL_GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define LOCAL_GL_MAX_VERTEX_ATTRIBS 0x8869
+#define LOCAL_GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
+#define LOCAL_GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define LOCAL_GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define LOCAL_GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define LOCAL_GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT 0x8DE2
+#define LOCAL_GL_MAX_VERTEX_HINT_PGI 0x1A22D
+#define LOCAL_GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define LOCAL_GL_MAX_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87C5
+#define LOCAL_GL_MAX_VERTEX_SHADER_INVARIANTS_EXT 0x87C7
+#define LOCAL_GL_MAX_VERTEX_SHADER_LOCALS_EXT 0x87C9
+#define LOCAL_GL_MAX_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87C8
+#define LOCAL_GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define LOCAL_GL_MAX_VERTEX_SHADER_VARIANTS_EXT 0x87C6
+#define LOCAL_GL_MAX_VERTEX_STREAMS 0x8E71
+#define LOCAL_GL_MAX_VERTEX_STREAMS_ATI 0x876B
+#define LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define LOCAL_GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C
+#define LOCAL_GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A
+#define LOCAL_GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define LOCAL_GL_MAX_VERTEX_UNITS_ARB 0x86A4
+#define LOCAL_GL_MAX_VERTEX_UNITS_OES 0x86A4
+#define LOCAL_GL_MAX_VERTEX_VARYING_COMPONENTS_ARB 0x8DDE
+#define LOCAL_GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+#define LOCAL_GL_MAX_VIEWPORTS 0x825B
+#define LOCAL_GL_MAX_VIEWPORTS_NV 0x825B
+#define LOCAL_GL_MAX_VIEWPORTS_OES 0x825B
+#define LOCAL_GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define LOCAL_GL_MAX_VIEWS_OVR 0x9631
+#define LOCAL_GL_MAX_WIDTH 0x827E
+#define LOCAL_GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14
+#define LOCAL_GL_MEDIUM_FLOAT 0x8DF1
+#define LOCAL_GL_MEDIUM_INT 0x8DF4
+#define LOCAL_GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6
+#define LOCAL_GL_MEMORY_ATTACHABLE_NV 0x95A8
+#define LOCAL_GL_MEMORY_ATTACHABLE_SIZE_NV 0x95A7
+#define LOCAL_GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV 0x9543
+#define LOCAL_GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV 0x92DF
+#define LOCAL_GL_MESH_OUTPUT_TYPE_NV 0x957B
+#define LOCAL_GL_MESH_PRIMITIVES_OUT_NV 0x957A
+#define LOCAL_GL_MESH_SHADER_BIT_NV 0x00000040
+#define LOCAL_GL_MESH_SHADER_NV 0x9559
+#define LOCAL_GL_MESH_SUBROUTINE_NV 0x957C
+#define LOCAL_GL_MESH_SUBROUTINE_UNIFORM_NV 0x957E
+#define LOCAL_GL_MESH_VERTICES_OUT_NV 0x9579
+#define LOCAL_GL_MESH_WORK_GROUP_SIZE_NV 0x953E
+#define LOCAL_GL_MIN 0x8007
+#define LOCAL_GL_MINMAX 0x802E
+#define LOCAL_GL_MINMAX_EXT 0x802E
+#define LOCAL_GL_MINMAX_FORMAT 0x802F
+#define LOCAL_GL_MINMAX_FORMAT_EXT 0x802F
+#define LOCAL_GL_MINMAX_SINK 0x8030
+#define LOCAL_GL_MINMAX_SINK_EXT 0x8030
+#define LOCAL_GL_MINOR_VERSION 0x821C
+#define LOCAL_GL_MINUS_CLAMPED_NV 0x92B3
+#define LOCAL_GL_MINUS_NV 0x929F
+#define LOCAL_GL_MIN_EXT 0x8007
+#define LOCAL_GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define LOCAL_GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV 0x8E5B
+#define LOCAL_GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
+#define LOCAL_GL_MIN_LOD_WARNING_AMD 0x919C
+#define LOCAL_GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904
+#define LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904
+#define LOCAL_GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define LOCAL_GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_ARB 0x8E5E
+#define LOCAL_GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET_NV 0x8E5E
+#define LOCAL_GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define LOCAL_GL_MIN_SAMPLE_SHADING_VALUE_ARB 0x8C37
+#define LOCAL_GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37
+#define LOCAL_GL_MIN_SPARSE_LEVEL_AMD 0x919B
+#define LOCAL_GL_MIPMAP 0x8293
+#define LOCAL_GL_MIRRORED_REPEAT 0x8370
+#define LOCAL_GL_MIRRORED_REPEAT_ARB 0x8370
+#define LOCAL_GL_MIRRORED_REPEAT_IBM 0x8370
+#define LOCAL_GL_MIRRORED_REPEAT_OES 0x8370
+#define LOCAL_GL_MIRROR_CLAMP_ATI 0x8742
+#define LOCAL_GL_MIRROR_CLAMP_EXT 0x8742
+#define LOCAL_GL_MIRROR_CLAMP_TO_BORDER_EXT 0x8912
+#define LOCAL_GL_MIRROR_CLAMP_TO_EDGE 0x8743
+#define LOCAL_GL_MIRROR_CLAMP_TO_EDGE_ATI 0x8743
+#define LOCAL_GL_MIRROR_CLAMP_TO_EDGE_EXT 0x8743
+#define LOCAL_GL_MITER_REVERT_NV 0x90A7
+#define LOCAL_GL_MITER_TRUNCATE_NV 0x90A8
+#define LOCAL_GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define LOCAL_GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define LOCAL_GL_MODELVIEW 0x1700
+#define LOCAL_GL_MODELVIEW0_ARB 0x1700
+#define LOCAL_GL_MODELVIEW0_EXT 0x1700
+#define LOCAL_GL_MODELVIEW0_MATRIX_EXT 0x0BA6
+#define LOCAL_GL_MODELVIEW0_STACK_DEPTH_EXT 0x0BA3
+#define LOCAL_GL_MODELVIEW10_ARB 0x872A
+#define LOCAL_GL_MODELVIEW11_ARB 0x872B
+#define LOCAL_GL_MODELVIEW12_ARB 0x872C
+#define LOCAL_GL_MODELVIEW13_ARB 0x872D
+#define LOCAL_GL_MODELVIEW14_ARB 0x872E
+#define LOCAL_GL_MODELVIEW15_ARB 0x872F
+#define LOCAL_GL_MODELVIEW16_ARB 0x8730
+#define LOCAL_GL_MODELVIEW17_ARB 0x8731
+#define LOCAL_GL_MODELVIEW18_ARB 0x8732
+#define LOCAL_GL_MODELVIEW19_ARB 0x8733
+#define LOCAL_GL_MODELVIEW1_ARB 0x850A
+#define LOCAL_GL_MODELVIEW1_EXT 0x850A
+#define LOCAL_GL_MODELVIEW1_MATRIX_EXT 0x8506
+#define LOCAL_GL_MODELVIEW1_STACK_DEPTH_EXT 0x8502
+#define LOCAL_GL_MODELVIEW20_ARB 0x8734
+#define LOCAL_GL_MODELVIEW21_ARB 0x8735
+#define LOCAL_GL_MODELVIEW22_ARB 0x8736
+#define LOCAL_GL_MODELVIEW23_ARB 0x8737
+#define LOCAL_GL_MODELVIEW24_ARB 0x8738
+#define LOCAL_GL_MODELVIEW25_ARB 0x8739
+#define LOCAL_GL_MODELVIEW26_ARB 0x873A
+#define LOCAL_GL_MODELVIEW27_ARB 0x873B
+#define LOCAL_GL_MODELVIEW28_ARB 0x873C
+#define LOCAL_GL_MODELVIEW29_ARB 0x873D
+#define LOCAL_GL_MODELVIEW2_ARB 0x8722
+#define LOCAL_GL_MODELVIEW30_ARB 0x873E
+#define LOCAL_GL_MODELVIEW31_ARB 0x873F
+#define LOCAL_GL_MODELVIEW3_ARB 0x8723
+#define LOCAL_GL_MODELVIEW4_ARB 0x8724
+#define LOCAL_GL_MODELVIEW5_ARB 0x8725
+#define LOCAL_GL_MODELVIEW6_ARB 0x8726
+#define LOCAL_GL_MODELVIEW7_ARB 0x8727
+#define LOCAL_GL_MODELVIEW8_ARB 0x8728
+#define LOCAL_GL_MODELVIEW9_ARB 0x8729
+#define LOCAL_GL_MODELVIEW_MATRIX 0x0BA6
+#define LOCAL_GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898D
+#define LOCAL_GL_MODELVIEW_PROJECTION_NV 0x8629
+#define LOCAL_GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define LOCAL_GL_MODULATE 0x2100
+#define LOCAL_GL_MODULATE_ADD_ATI 0x8744
+#define LOCAL_GL_MODULATE_COLOR_IMG 0x8C04
+#define LOCAL_GL_MODULATE_SIGNED_ADD_ATI 0x8745
+#define LOCAL_GL_MODULATE_SUBTRACT_ATI 0x8746
+#define LOCAL_GL_MOTION_ESTIMATION_SEARCH_BLOCK_X_QCOM 0x8C90
+#define LOCAL_GL_MOTION_ESTIMATION_SEARCH_BLOCK_Y_QCOM 0x8C91
+#define LOCAL_GL_MOVE_TO_CONTINUES_NV 0x90B6
+#define LOCAL_GL_MOVE_TO_NV 0x02
+#define LOCAL_GL_MOVE_TO_RESETS_NV 0x90B5
+#define LOCAL_GL_MOV_ATI 0x8961
+#define LOCAL_GL_MULT 0x0103
+#define LOCAL_GL_MULTICAST_GPUS_NV 0x92BA
+#define LOCAL_GL_MULTICAST_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9549
+#define LOCAL_GL_MULTIPLY 0x9294
+#define LOCAL_GL_MULTIPLY_KHR 0x9294
+#define LOCAL_GL_MULTIPLY_NV 0x9294
+#define LOCAL_GL_MULTISAMPLE 0x809D
+#define LOCAL_GL_MULTISAMPLES_NV 0x9371
+#define LOCAL_GL_MULTISAMPLE_3DFX 0x86B2
+#define LOCAL_GL_MULTISAMPLE_ARB 0x809D
+#define LOCAL_GL_MULTISAMPLE_BIT 0x20000000
+#define LOCAL_GL_MULTISAMPLE_BIT_3DFX 0x20000000
+#define LOCAL_GL_MULTISAMPLE_BIT_ARB 0x20000000
+#define LOCAL_GL_MULTISAMPLE_BIT_EXT 0x20000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000
+#define LOCAL_GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000
+#define LOCAL_GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
+#define LOCAL_GL_MULTISAMPLE_EXT 0x809D
+#define LOCAL_GL_MULTISAMPLE_FILTER_HINT_NV 0x8534
+#define LOCAL_GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382
+#define LOCAL_GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382
+#define LOCAL_GL_MULTISAMPLE_LINE_WIDTH_RANGE 0x9381
+#define LOCAL_GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381
+#define LOCAL_GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define LOCAL_GL_MULTISAMPLE_SGIS 0x809D
+#define LOCAL_GL_MULTIVIEW_EXT 0x90F1
+#define LOCAL_GL_MUL_ATI 0x8964
+#define LOCAL_GL_MVP_MATRIX_EXT 0x87E3
+#define LOCAL_GL_N3F_V3F 0x2A25
+#define LOCAL_GL_NAMED_STRING_LENGTH_ARB 0x8DE9
+#define LOCAL_GL_NAMED_STRING_TYPE_ARB 0x8DEA
+#define LOCAL_GL_NAME_LENGTH 0x92F9
+#define LOCAL_GL_NAME_STACK_DEPTH 0x0D70
+#define LOCAL_GL_NAND 0x150E
+#define LOCAL_GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI 0x1A203
+#define LOCAL_GL_NATIVE_GRAPHICS_END_HINT_PGI 0x1A204
+#define LOCAL_GL_NATIVE_GRAPHICS_HANDLE_PGI 0x1A202
+#define LOCAL_GL_NEAREST 0x2600
+#define LOCAL_GL_NEAREST_CLIPMAP_LINEAR_SGIX 0x844E
+#define LOCAL_GL_NEAREST_CLIPMAP_NEAREST_SGIX 0x844D
+#define LOCAL_GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define LOCAL_GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define LOCAL_GL_NEGATE_BIT_ATI 0x00000004
+#define LOCAL_GL_NEGATIVE_ONE_EXT 0x87DF
+#define LOCAL_GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define LOCAL_GL_NEGATIVE_ONE_TO_ONE_EXT 0x935E
+#define LOCAL_GL_NEGATIVE_W_EXT 0x87DC
+#define LOCAL_GL_NEGATIVE_X_EXT 0x87D9
+#define LOCAL_GL_NEGATIVE_Y_EXT 0x87DA
+#define LOCAL_GL_NEGATIVE_Z_EXT 0x87DB
+#define LOCAL_GL_NEVER 0x0200
+#define LOCAL_GL_NEXT_BUFFER_NV -2
+#define LOCAL_GL_NEXT_VIDEO_CAPTURE_BUFFER_STATUS_NV 0x9025
+#define LOCAL_GL_NICEST 0x1102
+#define LOCAL_GL_NONE 0
+#define LOCAL_GL_NONE_OES 0
+#define LOCAL_GL_NOOP 0x1505
+#define LOCAL_GL_NOP_COMMAND_NV 0x0001
+#define LOCAL_GL_NOR 0x1508
+#define LOCAL_GL_NORMALIZE 0x0BA1
+#define LOCAL_GL_NORMALIZED_RANGE_EXT 0x87E0
+#define LOCAL_GL_NORMAL_ARRAY 0x8075
+#define LOCAL_GL_NORMAL_ARRAY_ADDRESS_NV 0x8F22
+#define LOCAL_GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define LOCAL_GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define LOCAL_GL_NORMAL_ARRAY_COUNT_EXT 0x8080
+#define LOCAL_GL_NORMAL_ARRAY_EXT 0x8075
+#define LOCAL_GL_NORMAL_ARRAY_LENGTH_NV 0x8F2C
+#define LOCAL_GL_NORMAL_ARRAY_LIST_IBM 103071
+#define LOCAL_GL_NORMAL_ARRAY_LIST_STRIDE_IBM 103081
+#define LOCAL_GL_NORMAL_ARRAY_PARALLEL_POINTERS_INTEL 0x83F6
+#define LOCAL_GL_NORMAL_ARRAY_POINTER 0x808F
+#define LOCAL_GL_NORMAL_ARRAY_POINTER_EXT 0x808F
+#define LOCAL_GL_NORMAL_ARRAY_STRIDE 0x807F
+#define LOCAL_GL_NORMAL_ARRAY_STRIDE_EXT 0x807F
+#define LOCAL_GL_NORMAL_ARRAY_TYPE 0x807E
+#define LOCAL_GL_NORMAL_ARRAY_TYPE_EXT 0x807E
+#define LOCAL_GL_NORMAL_BIT_PGI 0x08000000
+#define LOCAL_GL_NORMAL_MAP 0x8511
+#define LOCAL_GL_NORMAL_MAP_ARB 0x8511
+#define LOCAL_GL_NORMAL_MAP_EXT 0x8511
+#define LOCAL_GL_NORMAL_MAP_NV 0x8511
+#define LOCAL_GL_NORMAL_MAP_OES 0x8511
+#define LOCAL_GL_NOTEQUAL 0x0205
+#define LOCAL_GL_NO_ERROR 0
+#define LOCAL_GL_NO_RESET_NOTIFICATION 0x8261
+#define LOCAL_GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define LOCAL_GL_NO_RESET_NOTIFICATION_EXT 0x8261
+#define LOCAL_GL_NO_RESET_NOTIFICATION_KHR 0x8261
+#define LOCAL_GL_NUM_ACTIVE_VARIABLES 0x9304
+#define LOCAL_GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define LOCAL_GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define LOCAL_GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
+#define LOCAL_GL_NUM_DEVICE_UUIDS_EXT 0x9596
+#define LOCAL_GL_NUM_DOWNSAMPLE_SCALES_IMG 0x913D
+#define LOCAL_GL_NUM_EXTENSIONS 0x821D
+#define LOCAL_GL_NUM_FILL_STREAMS_NV 0x8E29
+#define LOCAL_GL_NUM_FRAGMENT_CONSTANTS_ATI 0x896F
+#define LOCAL_GL_NUM_FRAGMENT_REGISTERS_ATI 0x896E
+#define LOCAL_GL_NUM_GENERAL_COMBINERS_NV 0x854E
+#define LOCAL_GL_NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI 0x8973
+#define LOCAL_GL_NUM_INSTRUCTIONS_PER_PASS_ATI 0x8971
+#define LOCAL_GL_NUM_INSTRUCTIONS_TOTAL_ATI 0x8972
+#define LOCAL_GL_NUM_LOOPBACK_COMPONENTS_ATI 0x8974
+#define LOCAL_GL_NUM_PASSES_ATI 0x8970
+#define LOCAL_GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define LOCAL_GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#define LOCAL_GL_NUM_SAMPLE_COUNTS 0x9380
+#define LOCAL_GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define LOCAL_GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define LOCAL_GL_NUM_SPARSE_LEVELS_ARB 0x91AA
+#define LOCAL_GL_NUM_SPARSE_LEVELS_EXT 0x91AA
+#define LOCAL_GL_NUM_SPIR_V_EXTENSIONS 0x9554
+#define LOCAL_GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6
+#define LOCAL_GL_NUM_TILING_TYPES_EXT 0x9582
+#define LOCAL_GL_NUM_VIDEO_CAPTURE_STREAMS_NV 0x9024
+#define LOCAL_GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8
+#define LOCAL_GL_NUM_VIRTUAL_PAGE_SIZES_EXT 0x91A8
+#define LOCAL_GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15
+#define LOCAL_GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89
+#define LOCAL_GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
+#define LOCAL_GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86
+#define LOCAL_GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87
+#define LOCAL_GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85
+#define LOCAL_GL_OBJECT_BUFFER_SIZE_ATI 0x8764
+#define LOCAL_GL_OBJECT_BUFFER_USAGE_ATI 0x8765
+#define LOCAL_GL_OBJECT_COMPILE_STATUS_ARB 0x8B81
+#define LOCAL_GL_OBJECT_DELETE_STATUS_ARB 0x8B80
+#define LOCAL_GL_OBJECT_DISTANCE_TO_LINE_SGIS 0x81F3
+#define LOCAL_GL_OBJECT_DISTANCE_TO_POINT_SGIS 0x81F1
+#define LOCAL_GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84
+#define LOCAL_GL_OBJECT_LINEAR 0x2401
+#define LOCAL_GL_OBJECT_LINEAR_NV 0x2401
+#define LOCAL_GL_OBJECT_LINE_SGIS 0x81F7
+#define LOCAL_GL_OBJECT_LINK_STATUS_ARB 0x8B82
+#define LOCAL_GL_OBJECT_PLANE 0x2501
+#define LOCAL_GL_OBJECT_POINT_SGIS 0x81F5
+#define LOCAL_GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88
+#define LOCAL_GL_OBJECT_SUBTYPE_ARB 0x8B4F
+#define LOCAL_GL_OBJECT_TYPE 0x9112
+#define LOCAL_GL_OBJECT_TYPE_APPLE 0x9112
+#define LOCAL_GL_OBJECT_TYPE_ARB 0x8B4E
+#define LOCAL_GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83
+#define LOCAL_GL_OCCLUSION_QUERY_EVENT_MASK_AMD 0x874F
+#define LOCAL_GL_OCCLUSION_TEST_HP 0x8165
+#define LOCAL_GL_OCCLUSION_TEST_RESULT_HP 0x8166
+#define LOCAL_GL_OFFSET 0x92FC
+#define LOCAL_GL_OFFSET_HILO_PROJECTIVE_TEXTURE_2D_NV 0x8856
+#define LOCAL_GL_OFFSET_HILO_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8857
+#define LOCAL_GL_OFFSET_HILO_TEXTURE_2D_NV 0x8854
+#define LOCAL_GL_OFFSET_HILO_TEXTURE_RECTANGLE_NV 0x8855
+#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
+#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
+#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
+#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
+#define LOCAL_GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
+#define LOCAL_GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
+#define LOCAL_GL_OFFSET_TEXTURE_2D_NV 0x86E8
+#define LOCAL_GL_OFFSET_TEXTURE_2D_SCALE_NV 0x86E2
+#define LOCAL_GL_OFFSET_TEXTURE_BIAS_NV 0x86E3
+#define LOCAL_GL_OFFSET_TEXTURE_MATRIX_NV 0x86E1
+#define LOCAL_GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C
+#define LOCAL_GL_OFFSET_TEXTURE_RECTANGLE_SCALE_NV 0x864D
+#define LOCAL_GL_OFFSET_TEXTURE_SCALE_NV 0x86E2
+#define LOCAL_GL_ONE 1
+#define LOCAL_GL_ONE_EXT 0x87DE
+#define LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define LOCAL_GL_ONE_MINUS_CONSTANT_ALPHA_EXT 0x8004
+#define LOCAL_GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define LOCAL_GL_ONE_MINUS_CONSTANT_COLOR_EXT 0x8002
+#define LOCAL_GL_ONE_MINUS_DST_ALPHA 0x0305
+#define LOCAL_GL_ONE_MINUS_DST_COLOR 0x0307
+#define LOCAL_GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define LOCAL_GL_ONE_MINUS_SRC1_ALPHA_EXT 0x88FB
+#define LOCAL_GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define LOCAL_GL_ONE_MINUS_SRC1_COLOR_EXT 0x88FA
+#define LOCAL_GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define LOCAL_GL_ONE_MINUS_SRC_COLOR 0x0301
+#define LOCAL_GL_OPERAND0_ALPHA 0x8598
+#define LOCAL_GL_OPERAND0_ALPHA_ARB 0x8598
+#define LOCAL_GL_OPERAND0_ALPHA_EXT 0x8598
+#define LOCAL_GL_OPERAND0_RGB 0x8590
+#define LOCAL_GL_OPERAND0_RGB_ARB 0x8590
+#define LOCAL_GL_OPERAND0_RGB_EXT 0x8590
+#define LOCAL_GL_OPERAND1_ALPHA 0x8599
+#define LOCAL_GL_OPERAND1_ALPHA_ARB 0x8599
+#define LOCAL_GL_OPERAND1_ALPHA_EXT 0x8599
+#define LOCAL_GL_OPERAND1_RGB 0x8591
+#define LOCAL_GL_OPERAND1_RGB_ARB 0x8591
+#define LOCAL_GL_OPERAND1_RGB_EXT 0x8591
+#define LOCAL_GL_OPERAND2_ALPHA 0x859A
+#define LOCAL_GL_OPERAND2_ALPHA_ARB 0x859A
+#define LOCAL_GL_OPERAND2_ALPHA_EXT 0x859A
+#define LOCAL_GL_OPERAND2_RGB 0x8592
+#define LOCAL_GL_OPERAND2_RGB_ARB 0x8592
+#define LOCAL_GL_OPERAND2_RGB_EXT 0x8592
+#define LOCAL_GL_OPERAND3_ALPHA_NV 0x859B
+#define LOCAL_GL_OPERAND3_RGB_NV 0x8593
+#define LOCAL_GL_OPTIMAL_TILING_EXT 0x9584
+#define LOCAL_GL_OP_ADD_EXT 0x8787
+#define LOCAL_GL_OP_CLAMP_EXT 0x878E
+#define LOCAL_GL_OP_CROSS_PRODUCT_EXT 0x8797
+#define LOCAL_GL_OP_DOT3_EXT 0x8784
+#define LOCAL_GL_OP_DOT4_EXT 0x8785
+#define LOCAL_GL_OP_EXP_BASE_2_EXT 0x8791
+#define LOCAL_GL_OP_FLOOR_EXT 0x878F
+#define LOCAL_GL_OP_FRAC_EXT 0x8789
+#define LOCAL_GL_OP_INDEX_EXT 0x8782
+#define LOCAL_GL_OP_LOG_BASE_2_EXT 0x8792
+#define LOCAL_GL_OP_MADD_EXT 0x8788
+#define LOCAL_GL_OP_MAX_EXT 0x878A
+#define LOCAL_GL_OP_MIN_EXT 0x878B
+#define LOCAL_GL_OP_MOV_EXT 0x8799
+#define LOCAL_GL_OP_MULTIPLY_MATRIX_EXT 0x8798
+#define LOCAL_GL_OP_MUL_EXT 0x8786
+#define LOCAL_GL_OP_NEGATE_EXT 0x8783
+#define LOCAL_GL_OP_POWER_EXT 0x8793
+#define LOCAL_GL_OP_RECIP_EXT 0x8794
+#define LOCAL_GL_OP_RECIP_SQRT_EXT 0x8795
+#define LOCAL_GL_OP_ROUND_EXT 0x8790
+#define LOCAL_GL_OP_SET_GE_EXT 0x878C
+#define LOCAL_GL_OP_SET_LT_EXT 0x878D
+#define LOCAL_GL_OP_SUB_EXT 0x8796
+#define LOCAL_GL_OR 0x1507
+#define LOCAL_GL_ORDER 0x0A01
+#define LOCAL_GL_OR_INVERTED 0x150D
+#define LOCAL_GL_OR_REVERSE 0x150B
+#define LOCAL_GL_OUTPUT_COLOR0_EXT 0x879B
+#define LOCAL_GL_OUTPUT_COLOR1_EXT 0x879C
+#define LOCAL_GL_OUTPUT_FOG_EXT 0x87BD
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD0_EXT 0x879D
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD10_EXT 0x87A7
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD11_EXT 0x87A8
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD12_EXT 0x87A9
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD13_EXT 0x87AA
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD14_EXT 0x87AB
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD15_EXT 0x87AC
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD16_EXT 0x87AD
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD17_EXT 0x87AE
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD18_EXT 0x87AF
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD19_EXT 0x87B0
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD1_EXT 0x879E
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD20_EXT 0x87B1
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD21_EXT 0x87B2
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD22_EXT 0x87B3
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD23_EXT 0x87B4
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD24_EXT 0x87B5
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD25_EXT 0x87B6
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD26_EXT 0x87B7
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD27_EXT 0x87B8
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD28_EXT 0x87B9
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD29_EXT 0x87BA
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD2_EXT 0x879F
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD30_EXT 0x87BB
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD31_EXT 0x87BC
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD3_EXT 0x87A0
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD4_EXT 0x87A1
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD5_EXT 0x87A2
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD6_EXT 0x87A3
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD7_EXT 0x87A4
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD8_EXT 0x87A5
+#define LOCAL_GL_OUTPUT_TEXTURE_COORD9_EXT 0x87A6
+#define LOCAL_GL_OUTPUT_VERTEX_EXT 0x879A
+#define LOCAL_GL_OUT_OF_MEMORY 0x0505
+#define LOCAL_GL_OVERLAY 0x9296
+#define LOCAL_GL_OVERLAY_KHR 0x9296
+#define LOCAL_GL_OVERLAY_NV 0x9296
+#define LOCAL_GL_PACK_ALIGNMENT 0x0D05
+#define LOCAL_GL_PACK_CMYK_HINT_EXT 0x800E
+#define LOCAL_GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define LOCAL_GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define LOCAL_GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define LOCAL_GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define LOCAL_GL_PACK_COMPRESSED_SIZE_SGIX 0x831C
+#define LOCAL_GL_PACK_IMAGE_DEPTH_SGIS 0x8131
+#define LOCAL_GL_PACK_IMAGE_HEIGHT 0x806C
+#define LOCAL_GL_PACK_IMAGE_HEIGHT_EXT 0x806C
+#define LOCAL_GL_PACK_INVERT_MESA 0x8758
+#define LOCAL_GL_PACK_LSB_FIRST 0x0D01
+#define LOCAL_GL_PACK_MAX_COMPRESSED_SIZE_SGIX 0x831B
+#define LOCAL_GL_PACK_RESAMPLE_OML 0x8984
+#define LOCAL_GL_PACK_RESAMPLE_SGIX 0x842E
+#define LOCAL_GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#define LOCAL_GL_PACK_ROW_BYTES_APPLE 0x8A15
+#define LOCAL_GL_PACK_ROW_LENGTH 0x0D02
+#define LOCAL_GL_PACK_SKIP_IMAGES 0x806B
+#define LOCAL_GL_PACK_SKIP_IMAGES_EXT 0x806B
+#define LOCAL_GL_PACK_SKIP_PIXELS 0x0D04
+#define LOCAL_GL_PACK_SKIP_ROWS 0x0D03
+#define LOCAL_GL_PACK_SKIP_VOLUMES_SGIS 0x8130
+#define LOCAL_GL_PACK_SUBSAMPLE_RATE_SGIX 0x85A0
+#define LOCAL_GL_PACK_SWAP_BYTES 0x0D00
+#define LOCAL_GL_PALETTE4_R5_G6_B5_OES 0x8B92
+#define LOCAL_GL_PALETTE4_RGB5_A1_OES 0x8B94
+#define LOCAL_GL_PALETTE4_RGB8_OES 0x8B90
+#define LOCAL_GL_PALETTE4_RGBA4_OES 0x8B93
+#define LOCAL_GL_PALETTE4_RGBA8_OES 0x8B91
+#define LOCAL_GL_PALETTE8_R5_G6_B5_OES 0x8B97
+#define LOCAL_GL_PALETTE8_RGB5_A1_OES 0x8B99
+#define LOCAL_GL_PALETTE8_RGB8_OES 0x8B95
+#define LOCAL_GL_PALETTE8_RGBA4_OES 0x8B98
+#define LOCAL_GL_PALETTE8_RGBA8_OES 0x8B96
+#define LOCAL_GL_PARALLEL_ARRAYS_INTEL 0x83F4
+#define LOCAL_GL_PARAMETER_BUFFER 0x80EE
+#define LOCAL_GL_PARAMETER_BUFFER_ARB 0x80EE
+#define LOCAL_GL_PARAMETER_BUFFER_BINDING 0x80EF
+#define LOCAL_GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF
+#define LOCAL_GL_PARTIAL_SUCCESS_NV 0x902E
+#define LOCAL_GL_PASS_THROUGH_NV 0x86E6
+#define LOCAL_GL_PASS_THROUGH_TOKEN 0x0700
+#define LOCAL_GL_PATCHES 0x000E
+#define LOCAL_GL_PATCHES_EXT 0x000E
+#define LOCAL_GL_PATCHES_OES 0x000E
+#define LOCAL_GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define LOCAL_GL_PATCH_DEFAULT_INNER_LEVEL_EXT 0x8E73
+#define LOCAL_GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define LOCAL_GL_PATCH_DEFAULT_OUTER_LEVEL_EXT 0x8E74
+#define LOCAL_GL_PATCH_VERTICES 0x8E72
+#define LOCAL_GL_PATCH_VERTICES_EXT 0x8E72
+#define LOCAL_GL_PATCH_VERTICES_OES 0x8E72
+#define LOCAL_GL_PATH_CLIENT_LENGTH_NV 0x907F
+#define LOCAL_GL_PATH_COMMAND_COUNT_NV 0x909D
+#define LOCAL_GL_PATH_COMPUTED_LENGTH_NV 0x90A0
+#define LOCAL_GL_PATH_COORD_COUNT_NV 0x909E
+#define LOCAL_GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF
+#define LOCAL_GL_PATH_DASH_ARRAY_COUNT_NV 0x909F
+#define LOCAL_GL_PATH_DASH_CAPS_NV 0x907B
+#define LOCAL_GL_PATH_DASH_OFFSET_NV 0x907E
+#define LOCAL_GL_PATH_DASH_OFFSET_RESET_NV 0x90B4
+#define LOCAL_GL_PATH_END_CAPS_NV 0x9076
+#define LOCAL_GL_PATH_ERROR_POSITION_NV 0x90AB
+#define LOCAL_GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1
+#define LOCAL_GL_PATH_FILL_COVER_MODE_NV 0x9082
+#define LOCAL_GL_PATH_FILL_MASK_NV 0x9081
+#define LOCAL_GL_PATH_FILL_MODE_NV 0x9080
+#define LOCAL_GL_PATH_FOG_GEN_MODE_NV 0x90AC
+#define LOCAL_GL_PATH_FORMAT_PS_NV 0x9071
+#define LOCAL_GL_PATH_FORMAT_SVG_NV 0x9070
+#define LOCAL_GL_PATH_GEN_COEFF_NV 0x90B1
+#define LOCAL_GL_PATH_GEN_COLOR_FORMAT_NV 0x90B2
+#define LOCAL_GL_PATH_GEN_COMPONENTS_NV 0x90B3
+#define LOCAL_GL_PATH_GEN_MODE_NV 0x90B0
+#define LOCAL_GL_PATH_INITIAL_DASH_CAP_NV 0x907C
+#define LOCAL_GL_PATH_INITIAL_END_CAP_NV 0x9077
+#define LOCAL_GL_PATH_JOIN_STYLE_NV 0x9079
+#define LOCAL_GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define LOCAL_GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define LOCAL_GL_PATH_MITER_LIMIT_NV 0x907A
+#define LOCAL_GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6
+#define LOCAL_GL_PATH_MODELVIEW_NV 0x1700
+#define LOCAL_GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3
+#define LOCAL_GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A
+#define LOCAL_GL_PATH_PROJECTION_MATRIX_NV 0x0BA7
+#define LOCAL_GL_PATH_PROJECTION_NV 0x1701
+#define LOCAL_GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define LOCAL_GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define LOCAL_GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define LOCAL_GL_PATH_STENCIL_FUNC_NV 0x90B7
+#define LOCAL_GL_PATH_STENCIL_REF_NV 0x90B8
+#define LOCAL_GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9
+#define LOCAL_GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2
+#define LOCAL_GL_PATH_STROKE_COVER_MODE_NV 0x9083
+#define LOCAL_GL_PATH_STROKE_MASK_NV 0x9084
+#define LOCAL_GL_PATH_STROKE_WIDTH_NV 0x9075
+#define LOCAL_GL_PATH_TERMINAL_DASH_CAP_NV 0x907D
+#define LOCAL_GL_PATH_TERMINAL_END_CAP_NV 0x9078
+#define LOCAL_GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define LOCAL_GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define LOCAL_GL_PERCENTAGE_AMD 0x8BC3
+#define LOCAL_GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0
+#define LOCAL_GL_PERFMON_RESULT_AMD 0x8BC6
+#define LOCAL_GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4
+#define LOCAL_GL_PERFMON_RESULT_SIZE_AMD 0x8BC5
+#define LOCAL_GL_PERFORMANCE_MONITOR_AMD 0x9152
+#define LOCAL_GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC
+#define LOCAL_GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB
+#define LOCAL_GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA
+#define LOCAL_GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8
+#define LOCAL_GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9
+#define LOCAL_GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF
+#define LOCAL_GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1
+#define LOCAL_GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2
+#define LOCAL_GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0
+#define LOCAL_GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE
+#define LOCAL_GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4
+#define LOCAL_GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3
+#define LOCAL_GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5
+#define LOCAL_GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9
+#define LOCAL_GL_PERFQUERY_FLUSH_INTEL 0x83FA
+#define LOCAL_GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001
+#define LOCAL_GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500
+#define LOCAL_GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD
+#define LOCAL_GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
+#define LOCAL_GL_PERFQUERY_WAIT_INTEL 0x83FB
+#define LOCAL_GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define LOCAL_GL_PERTURB_EXT 0x85AE
+#define LOCAL_GL_PER_GPU_STORAGE_BIT_NV 0x0800
+#define LOCAL_GL_PER_GPU_STORAGE_NV 0x9548
+#define LOCAL_GL_PER_STAGE_CONSTANTS_NV 0x8535
+#define LOCAL_GL_PHONG_HINT_WIN 0x80EB
+#define LOCAL_GL_PHONG_WIN 0x80EA
+#define LOCAL_GL_PINLIGHT_NV 0x92A8
+#define LOCAL_GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE
+#define LOCAL_GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF
+#define LOCAL_GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define LOCAL_GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080
+#define LOCAL_GL_PIXEL_COUNTER_BITS_NV 0x8864
+#define LOCAL_GL_PIXEL_COUNT_AVAILABLE_NV 0x8867
+#define LOCAL_GL_PIXEL_COUNT_NV 0x8866
+#define LOCAL_GL_PIXEL_CUBIC_WEIGHT_EXT 0x8333
+#define LOCAL_GL_PIXEL_FRAGMENT_ALPHA_SOURCE_SGIS 0x8355
+#define LOCAL_GL_PIXEL_FRAGMENT_RGB_SOURCE_SGIS 0x8354
+#define LOCAL_GL_PIXEL_GROUP_COLOR_SGIS 0x8356
+#define LOCAL_GL_PIXEL_MAG_FILTER_EXT 0x8331
+#define LOCAL_GL_PIXEL_MAP_A_TO_A 0x0C79
+#define LOCAL_GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define LOCAL_GL_PIXEL_MAP_B_TO_B 0x0C78
+#define LOCAL_GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define LOCAL_GL_PIXEL_MAP_G_TO_G 0x0C77
+#define LOCAL_GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define LOCAL_GL_PIXEL_MAP_I_TO_A 0x0C75
+#define LOCAL_GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define LOCAL_GL_PIXEL_MAP_I_TO_B 0x0C74
+#define LOCAL_GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define LOCAL_GL_PIXEL_MAP_I_TO_G 0x0C73
+#define LOCAL_GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define LOCAL_GL_PIXEL_MAP_I_TO_I 0x0C70
+#define LOCAL_GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define LOCAL_GL_PIXEL_MAP_I_TO_R 0x0C72
+#define LOCAL_GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define LOCAL_GL_PIXEL_MAP_R_TO_R 0x0C76
+#define LOCAL_GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define LOCAL_GL_PIXEL_MAP_S_TO_S 0x0C71
+#define LOCAL_GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define LOCAL_GL_PIXEL_MIN_FILTER_EXT 0x8332
+#define LOCAL_GL_PIXEL_MODE_BIT 0x00000020
+#define LOCAL_GL_PIXEL_PACK_BUFFER 0x88EB
+#define LOCAL_GL_PIXEL_PACK_BUFFER_ARB 0x88EB
+#define LOCAL_GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define LOCAL_GL_PIXEL_PACK_BUFFER_BINDING_ARB 0x88ED
+#define LOCAL_GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
+#define LOCAL_GL_PIXEL_PACK_BUFFER_BINDING_NV 0x88ED
+#define LOCAL_GL_PIXEL_PACK_BUFFER_EXT 0x88EB
+#define LOCAL_GL_PIXEL_PACK_BUFFER_NV 0x88EB
+#define LOCAL_GL_PIXEL_SUBSAMPLE_2424_SGIX 0x85A3
+#define LOCAL_GL_PIXEL_SUBSAMPLE_4242_SGIX 0x85A4
+#define LOCAL_GL_PIXEL_SUBSAMPLE_4444_SGIX 0x85A2
+#define LOCAL_GL_PIXEL_TEXTURE_SGIS 0x8353
+#define LOCAL_GL_PIXEL_TEX_GEN_ALPHA_LS_SGIX 0x8189
+#define LOCAL_GL_PIXEL_TEX_GEN_ALPHA_MS_SGIX 0x818A
+#define LOCAL_GL_PIXEL_TEX_GEN_ALPHA_NO_REPLACE_SGIX 0x8188
+#define LOCAL_GL_PIXEL_TEX_GEN_ALPHA_REPLACE_SGIX 0x8187
+#define LOCAL_GL_PIXEL_TEX_GEN_MODE_SGIX 0x832B
+#define LOCAL_GL_PIXEL_TEX_GEN_Q_CEILING_SGIX 0x8184
+#define LOCAL_GL_PIXEL_TEX_GEN_Q_FLOOR_SGIX 0x8186
+#define LOCAL_GL_PIXEL_TEX_GEN_Q_ROUND_SGIX 0x8185
+#define LOCAL_GL_PIXEL_TEX_GEN_SGIX 0x8139
+#define LOCAL_GL_PIXEL_TILE_BEST_ALIGNMENT_SGIX 0x813E
+#define LOCAL_GL_PIXEL_TILE_CACHE_INCREMENT_SGIX 0x813F
+#define LOCAL_GL_PIXEL_TILE_CACHE_SIZE_SGIX 0x8145
+#define LOCAL_GL_PIXEL_TILE_GRID_DEPTH_SGIX 0x8144
+#define LOCAL_GL_PIXEL_TILE_GRID_HEIGHT_SGIX 0x8143
+#define LOCAL_GL_PIXEL_TILE_GRID_WIDTH_SGIX 0x8142
+#define LOCAL_GL_PIXEL_TILE_HEIGHT_SGIX 0x8141
+#define LOCAL_GL_PIXEL_TILE_WIDTH_SGIX 0x8140
+#define LOCAL_GL_PIXEL_TRANSFORM_2D_EXT 0x8330
+#define LOCAL_GL_PIXEL_TRANSFORM_2D_MATRIX_EXT 0x8338
+#define LOCAL_GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT 0x8336
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING_ARB 0x88EF
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING_NV 0x88EF
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
+#define LOCAL_GL_PIXEL_UNPACK_BUFFER_NV 0x88EC
+#define LOCAL_GL_PLUS_CLAMPED_ALPHA_NV 0x92B2
+#define LOCAL_GL_PLUS_CLAMPED_NV 0x92B1
+#define LOCAL_GL_PLUS_DARKER_NV 0x9292
+#define LOCAL_GL_PLUS_NV 0x9291
+#define LOCAL_GL_PN_TRIANGLES_ATI 0x87F0
+#define LOCAL_GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
+#define LOCAL_GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
+#define LOCAL_GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
+#define LOCAL_GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
+#define LOCAL_GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
+#define LOCAL_GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
+#define LOCAL_GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
+#define LOCAL_GL_POINT 0x1B00
+#define LOCAL_GL_POINTS 0x0000
+#define LOCAL_GL_POINT_BIT 0x00000002
+#define LOCAL_GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define LOCAL_GL_POINT_DISTANCE_ATTENUATION_ARB 0x8129
+#define LOCAL_GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define LOCAL_GL_POINT_FADE_THRESHOLD_SIZE_ARB 0x8128
+#define LOCAL_GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128
+#define LOCAL_GL_POINT_FADE_THRESHOLD_SIZE_SGIS 0x8128
+#define LOCAL_GL_POINT_NV 0x1B00
+#define LOCAL_GL_POINT_SIZE 0x0B11
+#define LOCAL_GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F
+#define LOCAL_GL_POINT_SIZE_ARRAY_OES 0x8B9C
+#define LOCAL_GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C
+#define LOCAL_GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B
+#define LOCAL_GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A
+#define LOCAL_GL_POINT_SIZE_GRANULARITY 0x0B13
+#define LOCAL_GL_POINT_SIZE_MAX 0x8127
+#define LOCAL_GL_POINT_SIZE_MAX_ARB 0x8127
+#define LOCAL_GL_POINT_SIZE_MAX_EXT 0x8127
+#define LOCAL_GL_POINT_SIZE_MAX_SGIS 0x8127
+#define LOCAL_GL_POINT_SIZE_MIN 0x8126
+#define LOCAL_GL_POINT_SIZE_MIN_ARB 0x8126
+#define LOCAL_GL_POINT_SIZE_MIN_EXT 0x8126
+#define LOCAL_GL_POINT_SIZE_MIN_SGIS 0x8126
+#define LOCAL_GL_POINT_SIZE_RANGE 0x0B12
+#define LOCAL_GL_POINT_SMOOTH 0x0B10
+#define LOCAL_GL_POINT_SMOOTH_HINT 0x0C51
+#define LOCAL_GL_POINT_SPRITE 0x8861
+#define LOCAL_GL_POINT_SPRITE_ARB 0x8861
+#define LOCAL_GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define LOCAL_GL_POINT_SPRITE_NV 0x8861
+#define LOCAL_GL_POINT_SPRITE_OES 0x8861
+#define LOCAL_GL_POINT_SPRITE_R_MODE_NV 0x8863
+#define LOCAL_GL_POINT_TOKEN 0x0701
+#define LOCAL_GL_POLYGON 0x0009
+#define LOCAL_GL_POLYGON_BIT 0x00000008
+#define LOCAL_GL_POLYGON_MODE 0x0B40
+#define LOCAL_GL_POLYGON_MODE_NV 0x0B40
+#define LOCAL_GL_POLYGON_OFFSET_BIAS_EXT 0x8039
+#define LOCAL_GL_POLYGON_OFFSET_CLAMP 0x8E1B
+#define LOCAL_GL_POLYGON_OFFSET_CLAMP_EXT 0x8E1B
+#define LOCAL_GL_POLYGON_OFFSET_COMMAND_NV 0x000E
+#define LOCAL_GL_POLYGON_OFFSET_EXT 0x8037
+#define LOCAL_GL_POLYGON_OFFSET_FACTOR 0x8038
+#define LOCAL_GL_POLYGON_OFFSET_FACTOR_EXT 0x8038
+#define LOCAL_GL_POLYGON_OFFSET_FILL 0x8037
+#define LOCAL_GL_POLYGON_OFFSET_LINE 0x2A02
+#define LOCAL_GL_POLYGON_OFFSET_LINE_NV 0x2A02
+#define LOCAL_GL_POLYGON_OFFSET_POINT 0x2A01
+#define LOCAL_GL_POLYGON_OFFSET_POINT_NV 0x2A01
+#define LOCAL_GL_POLYGON_OFFSET_UNITS 0x2A00
+#define LOCAL_GL_POLYGON_SMOOTH 0x0B41
+#define LOCAL_GL_POLYGON_SMOOTH_HINT 0x0C53
+#define LOCAL_GL_POLYGON_STIPPLE 0x0B42
+#define LOCAL_GL_POLYGON_STIPPLE_BIT 0x00000010
+#define LOCAL_GL_POLYGON_TOKEN 0x0703
+#define LOCAL_GL_POSITION 0x1203
+#define LOCAL_GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB
+#define LOCAL_GL_POST_COLOR_MATRIX_ALPHA_BIAS_SGI 0x80BB
+#define LOCAL_GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7
+#define LOCAL_GL_POST_COLOR_MATRIX_ALPHA_SCALE_SGI 0x80B7
+#define LOCAL_GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA
+#define LOCAL_GL_POST_COLOR_MATRIX_BLUE_BIAS_SGI 0x80BA
+#define LOCAL_GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6
+#define LOCAL_GL_POST_COLOR_MATRIX_BLUE_SCALE_SGI 0x80B6
+#define LOCAL_GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
+#define LOCAL_GL_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D2
+#define LOCAL_GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9
+#define LOCAL_GL_POST_COLOR_MATRIX_GREEN_BIAS_SGI 0x80B9
+#define LOCAL_GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5
+#define LOCAL_GL_POST_COLOR_MATRIX_GREEN_SCALE_SGI 0x80B5
+#define LOCAL_GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8
+#define LOCAL_GL_POST_COLOR_MATRIX_RED_BIAS_SGI 0x80B8
+#define LOCAL_GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4
+#define LOCAL_GL_POST_COLOR_MATRIX_RED_SCALE_SGI 0x80B4
+#define LOCAL_GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023
+#define LOCAL_GL_POST_CONVOLUTION_ALPHA_BIAS_EXT 0x8023
+#define LOCAL_GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F
+#define LOCAL_GL_POST_CONVOLUTION_ALPHA_SCALE_EXT 0x801F
+#define LOCAL_GL_POST_CONVOLUTION_BLUE_BIAS 0x8022
+#define LOCAL_GL_POST_CONVOLUTION_BLUE_BIAS_EXT 0x8022
+#define LOCAL_GL_POST_CONVOLUTION_BLUE_SCALE 0x801E
+#define LOCAL_GL_POST_CONVOLUTION_BLUE_SCALE_EXT 0x801E
+#define LOCAL_GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
+#define LOCAL_GL_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D1
+#define LOCAL_GL_POST_CONVOLUTION_GREEN_BIAS 0x8021
+#define LOCAL_GL_POST_CONVOLUTION_GREEN_BIAS_EXT 0x8021
+#define LOCAL_GL_POST_CONVOLUTION_GREEN_SCALE 0x801D
+#define LOCAL_GL_POST_CONVOLUTION_GREEN_SCALE_EXT 0x801D
+#define LOCAL_GL_POST_CONVOLUTION_RED_BIAS 0x8020
+#define LOCAL_GL_POST_CONVOLUTION_RED_BIAS_EXT 0x8020
+#define LOCAL_GL_POST_CONVOLUTION_RED_SCALE 0x801C
+#define LOCAL_GL_POST_CONVOLUTION_RED_SCALE_EXT 0x801C
+#define LOCAL_GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8162
+#define LOCAL_GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX 0x817B
+#define LOCAL_GL_POST_TEXTURE_FILTER_BIAS_SGIX 0x8179
+#define LOCAL_GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX 0x817C
+#define LOCAL_GL_POST_TEXTURE_FILTER_SCALE_SGIX 0x817A
+#define LOCAL_GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8
+#define LOCAL_GL_PRESENT_DURATION_NV 0x8E2B
+#define LOCAL_GL_PRESENT_TIME_NV 0x8E2A
+#define LOCAL_GL_PRESERVE_ATI 0x8762
+#define LOCAL_GL_PREVIOUS 0x8578
+#define LOCAL_GL_PREVIOUS_ARB 0x8578
+#define LOCAL_GL_PREVIOUS_EXT 0x8578
+#define LOCAL_GL_PREVIOUS_TEXTURE_INPUT_NV 0x86E4
+#define LOCAL_GL_PRIMARY_COLOR 0x8577
+#define LOCAL_GL_PRIMARY_COLOR_ARB 0x8577
+#define LOCAL_GL_PRIMARY_COLOR_EXT 0x8577
+#define LOCAL_GL_PRIMARY_COLOR_NV 0x852C
+#define LOCAL_GL_PRIMITIVES_GENERATED 0x8C87
+#define LOCAL_GL_PRIMITIVES_GENERATED_EXT 0x8C87
+#define LOCAL_GL_PRIMITIVES_GENERATED_NV 0x8C87
+#define LOCAL_GL_PRIMITIVES_GENERATED_OES 0x8C87
+#define LOCAL_GL_PRIMITIVES_SUBMITTED 0x82EF
+#define LOCAL_GL_PRIMITIVES_SUBMITTED_ARB 0x82EF
+#define LOCAL_GL_PRIMITIVE_BOUNDING_BOX 0x92BE
+#define LOCAL_GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE
+#define LOCAL_GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE
+#define LOCAL_GL_PRIMITIVE_BOUNDING_BOX_OES 0x92BE
+#define LOCAL_GL_PRIMITIVE_ID_NV 0x8C7C
+#define LOCAL_GL_PRIMITIVE_RESTART 0x8F9D
+#define LOCAL_GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define LOCAL_GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define LOCAL_GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define LOCAL_GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define LOCAL_GL_PRIMITIVE_RESTART_INDEX_NV 0x8559
+#define LOCAL_GL_PRIMITIVE_RESTART_NV 0x8558
+#define LOCAL_GL_PROGRAM 0x82E2
+#define LOCAL_GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341
+#define LOCAL_GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define LOCAL_GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340
+#define LOCAL_GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define LOCAL_GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
+#define LOCAL_GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
+#define LOCAL_GL_PROGRAM_ATTRIBS_ARB 0x88AC
+#define LOCAL_GL_PROGRAM_ATTRIB_COMPONENTS_NV 0x8906
+#define LOCAL_GL_PROGRAM_BINARY_ANGLE 0x93A6
+#define LOCAL_GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define LOCAL_GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#define LOCAL_GL_PROGRAM_BINARY_FORMAT_MESA 0x875F
+#define LOCAL_GL_PROGRAM_BINARY_LENGTH 0x8741
+#define LOCAL_GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#define LOCAL_GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define LOCAL_GL_PROGRAM_BINDING_ARB 0x8677
+#define LOCAL_GL_PROGRAM_ERROR_POSITION_ARB 0x864B
+#define LOCAL_GL_PROGRAM_ERROR_POSITION_NV 0x864B
+#define LOCAL_GL_PROGRAM_ERROR_STRING_ARB 0x8874
+#define LOCAL_GL_PROGRAM_ERROR_STRING_NV 0x8874
+#define LOCAL_GL_PROGRAM_FORMAT_ARB 0x8876
+#define LOCAL_GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
+#define LOCAL_GL_PROGRAM_INPUT 0x92E3
+#define LOCAL_GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
+#define LOCAL_GL_PROGRAM_KHR 0x82E2
+#define LOCAL_GL_PROGRAM_LENGTH_ARB 0x8627
+#define LOCAL_GL_PROGRAM_LENGTH_NV 0x8627
+#define LOCAL_GL_PROGRAM_MATRIX_EXT 0x8E2D
+#define LOCAL_GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
+#define LOCAL_GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
+#define LOCAL_GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
+#define LOCAL_GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
+#define LOCAL_GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
+#define LOCAL_GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
+#define LOCAL_GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
+#define LOCAL_GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
+#define LOCAL_GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
+#define LOCAL_GL_PROGRAM_OBJECT_ARB 0x8B40
+#define LOCAL_GL_PROGRAM_OBJECT_EXT 0x8B40
+#define LOCAL_GL_PROGRAM_OUTPUT 0x92E4
+#define LOCAL_GL_PROGRAM_PARAMETERS_ARB 0x88A8
+#define LOCAL_GL_PROGRAM_PARAMETER_NV 0x8644
+#define LOCAL_GL_PROGRAM_PIPELINE 0x82E4
+#define LOCAL_GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define LOCAL_GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A
+#define LOCAL_GL_PROGRAM_PIPELINE_KHR 0x82E4
+#define LOCAL_GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
+#define LOCAL_GL_PROGRAM_POINT_SIZE 0x8642
+#define LOCAL_GL_PROGRAM_POINT_SIZE_ARB 0x8642
+#define LOCAL_GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#define LOCAL_GL_PROGRAM_RESIDENT_NV 0x8647
+#define LOCAL_GL_PROGRAM_RESULT_COMPONENTS_NV 0x8907
+#define LOCAL_GL_PROGRAM_SEPARABLE 0x8258
+#define LOCAL_GL_PROGRAM_SEPARABLE_EXT 0x8258
+#define LOCAL_GL_PROGRAM_STRING_ARB 0x8628
+#define LOCAL_GL_PROGRAM_STRING_NV 0x8628
+#define LOCAL_GL_PROGRAM_TARGET_NV 0x8646
+#define LOCAL_GL_PROGRAM_TEMPORARIES_ARB 0x88A4
+#define LOCAL_GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
+#define LOCAL_GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
+#define LOCAL_GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
+#define LOCAL_GL_PROJECTION 0x1701
+#define LOCAL_GL_PROJECTION_MATRIX 0x0BA7
+#define LOCAL_GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898E
+#define LOCAL_GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define LOCAL_GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B
+#define LOCAL_GL_PROVOKING_VERTEX 0x8E4F
+#define LOCAL_GL_PROVOKING_VERTEX_EXT 0x8E4F
+#define LOCAL_GL_PROXY_COLOR_TABLE 0x80D3
+#define LOCAL_GL_PROXY_COLOR_TABLE_SGI 0x80D3
+#define LOCAL_GL_PROXY_HISTOGRAM 0x8025
+#define LOCAL_GL_PROXY_HISTOGRAM_EXT 0x8025
+#define LOCAL_GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
+#define LOCAL_GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE_SGI 0x80D5
+#define LOCAL_GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
+#define LOCAL_GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI 0x80D4
+#define LOCAL_GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP 0x8163
+#define LOCAL_GL_PROXY_TEXTURE_1D 0x8063
+#define LOCAL_GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define LOCAL_GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19
+#define LOCAL_GL_PROXY_TEXTURE_1D_EXT 0x8063
+#define LOCAL_GL_PROXY_TEXTURE_1D_STACK_MESAX 0x875B
+#define LOCAL_GL_PROXY_TEXTURE_2D 0x8064
+#define LOCAL_GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define LOCAL_GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B
+#define LOCAL_GL_PROXY_TEXTURE_2D_EXT 0x8064
+#define LOCAL_GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define LOCAL_GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define LOCAL_GL_PROXY_TEXTURE_2D_STACK_MESAX 0x875C
+#define LOCAL_GL_PROXY_TEXTURE_3D 0x8070
+#define LOCAL_GL_PROXY_TEXTURE_3D_EXT 0x8070
+#define LOCAL_GL_PROXY_TEXTURE_4D_SGIS 0x8135
+#define LOCAL_GL_PROXY_TEXTURE_COLOR_TABLE_SGI 0x80BD
+#define LOCAL_GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define LOCAL_GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
+#define LOCAL_GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define LOCAL_GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB 0x900B
+#define LOCAL_GL_PROXY_TEXTURE_CUBE_MAP_EXT 0x851B
+#define LOCAL_GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define LOCAL_GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
+#define LOCAL_GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
+#define LOCAL_GL_PURGEABLE_APPLE 0x8A1D
+#define LOCAL_GL_PURGED_CONTEXT_RESET_NV 0x92BB
+#define LOCAL_GL_Q 0x2003
+#define LOCAL_GL_QUADRATIC_ATTENUATION 0x1209
+#define LOCAL_GL_QUADRATIC_CURVE_TO_NV 0x0A
+#define LOCAL_GL_QUADS 0x0007
+#define LOCAL_GL_QUADS_EXT 0x0007
+#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
+#define LOCAL_GL_QUADS_OES 0x0007
+#define LOCAL_GL_QUAD_ALPHA4_SGIS 0x811E
+#define LOCAL_GL_QUAD_ALPHA8_SGIS 0x811F
+#define LOCAL_GL_QUAD_INTENSITY4_SGIS 0x8122
+#define LOCAL_GL_QUAD_INTENSITY8_SGIS 0x8123
+#define LOCAL_GL_QUAD_LUMINANCE4_SGIS 0x8120
+#define LOCAL_GL_QUAD_LUMINANCE8_SGIS 0x8121
+#define LOCAL_GL_QUAD_MESH_SUN 0x8614
+#define LOCAL_GL_QUAD_STRIP 0x0008
+#define LOCAL_GL_QUAD_TEXTURE_SELECT_SGIS 0x8125
+#define LOCAL_GL_QUARTER_BIT_ATI 0x00000010
+#define LOCAL_GL_QUERY 0x82E3
+#define LOCAL_GL_QUERY_ALL_EVENT_BITS_AMD 0xFFFFFFFF
+#define LOCAL_GL_QUERY_BUFFER 0x9192
+#define LOCAL_GL_QUERY_BUFFER_AMD 0x9192
+#define LOCAL_GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define LOCAL_GL_QUERY_BUFFER_BINDING 0x9193
+#define LOCAL_GL_QUERY_BUFFER_BINDING_AMD 0x9193
+#define LOCAL_GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define LOCAL_GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
+#define LOCAL_GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16
+#define LOCAL_GL_QUERY_BY_REGION_WAIT 0x8E15
+#define LOCAL_GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
+#define LOCAL_GL_QUERY_BY_REGION_WAIT_NV 0x8E15
+#define LOCAL_GL_QUERY_COUNTER_BITS 0x8864
+#define LOCAL_GL_QUERY_COUNTER_BITS_ARB 0x8864
+#define LOCAL_GL_QUERY_COUNTER_BITS_EXT 0x8864
+#define LOCAL_GL_QUERY_DEPTH_BOUNDS_FAIL_EVENT_BIT_AMD 0x00000008
+#define LOCAL_GL_QUERY_DEPTH_FAIL_EVENT_BIT_AMD 0x00000002
+#define LOCAL_GL_QUERY_DEPTH_PASS_EVENT_BIT_AMD 0x00000001
+#define LOCAL_GL_QUERY_KHR 0x82E3
+#define LOCAL_GL_QUERY_NO_WAIT 0x8E14
+#define LOCAL_GL_QUERY_NO_WAIT_INVERTED 0x8E18
+#define LOCAL_GL_QUERY_NO_WAIT_NV 0x8E14
+#define LOCAL_GL_QUERY_OBJECT_AMD 0x9153
+#define LOCAL_GL_QUERY_OBJECT_EXT 0x9153
+#define LOCAL_GL_QUERY_RESOURCE_BUFFEROBJECT_NV 0x9547
+#define LOCAL_GL_QUERY_RESOURCE_MEMTYPE_VIDMEM_NV 0x9542
+#define LOCAL_GL_QUERY_RESOURCE_RENDERBUFFER_NV 0x9546
+#define LOCAL_GL_QUERY_RESOURCE_SYS_RESERVED_NV 0x9544
+#define LOCAL_GL_QUERY_RESOURCE_TEXTURE_NV 0x9545
+#define LOCAL_GL_QUERY_RESOURCE_TYPE_VIDMEM_ALLOC_NV 0x9540
+#define LOCAL_GL_QUERY_RESULT 0x8866
+#define LOCAL_GL_QUERY_RESULT_ARB 0x8866
+#define LOCAL_GL_QUERY_RESULT_AVAILABLE 0x8867
+#define LOCAL_GL_QUERY_RESULT_AVAILABLE_ARB 0x8867
+#define LOCAL_GL_QUERY_RESULT_AVAILABLE_EXT 0x8867
+#define LOCAL_GL_QUERY_RESULT_EXT 0x8866
+#define LOCAL_GL_QUERY_RESULT_NO_WAIT 0x9194
+#define LOCAL_GL_QUERY_RESULT_NO_WAIT_AMD 0x9194
+#define LOCAL_GL_QUERY_STENCIL_FAIL_EVENT_BIT_AMD 0x00000004
+#define LOCAL_GL_QUERY_TARGET 0x82EA
+#define LOCAL_GL_QUERY_WAIT 0x8E13
+#define LOCAL_GL_QUERY_WAIT_INVERTED 0x8E17
+#define LOCAL_GL_QUERY_WAIT_NV 0x8E13
+#define LOCAL_GL_R 0x2002
+#define LOCAL_GL_R11F_G11F_B10F 0x8C3A
+#define LOCAL_GL_R11F_G11F_B10F_APPLE 0x8C3A
+#define LOCAL_GL_R11F_G11F_B10F_EXT 0x8C3A
+#define LOCAL_GL_R16 0x822A
+#define LOCAL_GL_R16F 0x822D
+#define LOCAL_GL_R16F_EXT 0x822D
+#define LOCAL_GL_R16I 0x8233
+#define LOCAL_GL_R16UI 0x8234
+#define LOCAL_GL_R16_EXT 0x822A
+#define LOCAL_GL_R16_SNORM 0x8F98
+#define LOCAL_GL_R16_SNORM_EXT 0x8F98
+#define LOCAL_GL_R1UI_C3F_V3F_SUN 0x85C6
+#define LOCAL_GL_R1UI_C4F_N3F_V3F_SUN 0x85C8
+#define LOCAL_GL_R1UI_C4UB_V3F_SUN 0x85C5
+#define LOCAL_GL_R1UI_N3F_V3F_SUN 0x85C7
+#define LOCAL_GL_R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB
+#define LOCAL_GL_R1UI_T2F_N3F_V3F_SUN 0x85CA
+#define LOCAL_GL_R1UI_T2F_V3F_SUN 0x85C9
+#define LOCAL_GL_R1UI_V3F_SUN 0x85C4
+#define LOCAL_GL_R32F 0x822E
+#define LOCAL_GL_R32F_EXT 0x822E
+#define LOCAL_GL_R32I 0x8235
+#define LOCAL_GL_R32UI 0x8236
+#define LOCAL_GL_R3_G3_B2 0x2A10
+#define LOCAL_GL_R8 0x8229
+#define LOCAL_GL_R8I 0x8231
+#define LOCAL_GL_R8UI 0x8232
+#define LOCAL_GL_R8_EXT 0x8229
+#define LOCAL_GL_R8_SNORM 0x8F94
+#define LOCAL_GL_RASTERIZER_DISCARD 0x8C89
+#define LOCAL_GL_RASTERIZER_DISCARD_EXT 0x8C89
+#define LOCAL_GL_RASTERIZER_DISCARD_NV 0x8C89
+#define LOCAL_GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define LOCAL_GL_RASTER_MULTISAMPLE_EXT 0x9327
+#define LOCAL_GL_RASTER_POSITION_UNCLIPPED_IBM 0x19262
+#define LOCAL_GL_RASTER_SAMPLES_EXT 0x9328
+#define LOCAL_GL_READ_BUFFER 0x0C02
+#define LOCAL_GL_READ_BUFFER_EXT 0x0C02
+#define LOCAL_GL_READ_BUFFER_NV 0x0C02
+#define LOCAL_GL_READ_FRAMEBUFFER 0x8CA8
+#define LOCAL_GL_READ_FRAMEBUFFER_ANGLE 0x8CA8
+#define LOCAL_GL_READ_FRAMEBUFFER_APPLE 0x8CA8
+#define LOCAL_GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define LOCAL_GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA
+#define LOCAL_GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA
+#define LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
+#define LOCAL_GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA
+#define LOCAL_GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#define LOCAL_GL_READ_FRAMEBUFFER_NV 0x8CA8
+#define LOCAL_GL_READ_ONLY 0x88B8
+#define LOCAL_GL_READ_ONLY_ARB 0x88B8
+#define LOCAL_GL_READ_PIXELS 0x828C
+#define LOCAL_GL_READ_PIXELS_FORMAT 0x828D
+#define LOCAL_GL_READ_PIXELS_TYPE 0x828E
+#define LOCAL_GL_READ_PIXEL_DATA_RANGE_LENGTH_NV 0x887B
+#define LOCAL_GL_READ_PIXEL_DATA_RANGE_NV 0x8879
+#define LOCAL_GL_READ_PIXEL_DATA_RANGE_POINTER_NV 0x887D
+#define LOCAL_GL_READ_WRITE 0x88BA
+#define LOCAL_GL_READ_WRITE_ARB 0x88BA
+#define LOCAL_GL_RECIP_ADD_SIGNED_ALPHA_IMG 0x8C05
+#define LOCAL_GL_RECLAIM_MEMORY_HINT_PGI 0x1A1FE
+#define LOCAL_GL_RECT_NV 0xF6
+#define LOCAL_GL_RED 0x1903
+#define LOCAL_GL_REDUCE 0x8016
+#define LOCAL_GL_REDUCE_EXT 0x8016
+#define LOCAL_GL_RED_BIAS 0x0D15
+#define LOCAL_GL_RED_BITS 0x0D52
+#define LOCAL_GL_RED_BIT_ATI 0x00000001
+#define LOCAL_GL_RED_EXT 0x1903
+#define LOCAL_GL_RED_INTEGER 0x8D94
+#define LOCAL_GL_RED_INTEGER_EXT 0x8D94
+#define LOCAL_GL_RED_MAX_CLAMP_INGR 0x8564
+#define LOCAL_GL_RED_MIN_CLAMP_INGR 0x8560
+#define LOCAL_GL_RED_NV 0x1903
+#define LOCAL_GL_RED_SCALE 0x0D14
+#define LOCAL_GL_RED_SNORM 0x8F90
+#define LOCAL_GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define LOCAL_GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define LOCAL_GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define LOCAL_GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309
+#define LOCAL_GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+#define LOCAL_GL_REFERENCED_BY_MESH_SHADER_NV 0x95A0
+#define LOCAL_GL_REFERENCED_BY_TASK_SHADER_NV 0x95A1
+#define LOCAL_GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define LOCAL_GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307
+#define LOCAL_GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define LOCAL_GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define LOCAL_GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308
+#define LOCAL_GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define LOCAL_GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define LOCAL_GL_REFERENCE_PLANE_EQUATION_SGIX 0x817E
+#define LOCAL_GL_REFERENCE_PLANE_SGIX 0x817D
+#define LOCAL_GL_REFLECTION_MAP 0x8512
+#define LOCAL_GL_REFLECTION_MAP_ARB 0x8512
+#define LOCAL_GL_REFLECTION_MAP_EXT 0x8512
+#define LOCAL_GL_REFLECTION_MAP_NV 0x8512
+#define LOCAL_GL_REFLECTION_MAP_OES 0x8512
+#define LOCAL_GL_REGISTER_COMBINERS_NV 0x8522
+#define LOCAL_GL_REG_0_ATI 0x8921
+#define LOCAL_GL_REG_10_ATI 0x892B
+#define LOCAL_GL_REG_11_ATI 0x892C
+#define LOCAL_GL_REG_12_ATI 0x892D
+#define LOCAL_GL_REG_13_ATI 0x892E
+#define LOCAL_GL_REG_14_ATI 0x892F
+#define LOCAL_GL_REG_15_ATI 0x8930
+#define LOCAL_GL_REG_16_ATI 0x8931
+#define LOCAL_GL_REG_17_ATI 0x8932
+#define LOCAL_GL_REG_18_ATI 0x8933
+#define LOCAL_GL_REG_19_ATI 0x8934
+#define LOCAL_GL_REG_1_ATI 0x8922
+#define LOCAL_GL_REG_20_ATI 0x8935
+#define LOCAL_GL_REG_21_ATI 0x8936
+#define LOCAL_GL_REG_22_ATI 0x8937
+#define LOCAL_GL_REG_23_ATI 0x8938
+#define LOCAL_GL_REG_24_ATI 0x8939
+#define LOCAL_GL_REG_25_ATI 0x893A
+#define LOCAL_GL_REG_26_ATI 0x893B
+#define LOCAL_GL_REG_27_ATI 0x893C
+#define LOCAL_GL_REG_28_ATI 0x893D
+#define LOCAL_GL_REG_29_ATI 0x893E
+#define LOCAL_GL_REG_2_ATI 0x8923
+#define LOCAL_GL_REG_30_ATI 0x893F
+#define LOCAL_GL_REG_31_ATI 0x8940
+#define LOCAL_GL_REG_3_ATI 0x8924
+#define LOCAL_GL_REG_4_ATI 0x8925
+#define LOCAL_GL_REG_5_ATI 0x8926
+#define LOCAL_GL_REG_6_ATI 0x8927
+#define LOCAL_GL_REG_7_ATI 0x8928
+#define LOCAL_GL_REG_8_ATI 0x8929
+#define LOCAL_GL_REG_9_ATI 0x892A
+#define LOCAL_GL_RELATIVE_ARC_TO_NV 0xFF
+#define LOCAL_GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B
+#define LOCAL_GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D
+#define LOCAL_GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define LOCAL_GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17
+#define LOCAL_GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19
+#define LOCAL_GL_RELATIVE_LINE_TO_NV 0x05
+#define LOCAL_GL_RELATIVE_MOVE_TO_NV 0x03
+#define LOCAL_GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define LOCAL_GL_RELATIVE_RECT_NV 0xF7
+#define LOCAL_GL_RELATIVE_ROUNDED_RECT2_NV 0xEB
+#define LOCAL_GL_RELATIVE_ROUNDED_RECT4_NV 0xED
+#define LOCAL_GL_RELATIVE_ROUNDED_RECT8_NV 0xEF
+#define LOCAL_GL_RELATIVE_ROUNDED_RECT_NV 0xE9
+#define LOCAL_GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13
+#define LOCAL_GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15
+#define LOCAL_GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define LOCAL_GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define LOCAL_GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09
+#define LOCAL_GL_RELEASED_APPLE 0x8A19
+#define LOCAL_GL_RENDER 0x1C00
+#define LOCAL_GL_RENDERBUFFER 0x8D41
+#define LOCAL_GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define LOCAL_GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
+#define LOCAL_GL_RENDERBUFFER_ALPHA_SIZE_OES 0x8D53
+#define LOCAL_GL_RENDERBUFFER_BINDING 0x8CA7
+#define LOCAL_GL_RENDERBUFFER_BINDING_ANGLE 0x8CA7
+#define LOCAL_GL_RENDERBUFFER_BINDING_EXT 0x8CA7
+#define LOCAL_GL_RENDERBUFFER_BINDING_OES 0x8CA7
+#define LOCAL_GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define LOCAL_GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
+#define LOCAL_GL_RENDERBUFFER_BLUE_SIZE_OES 0x8D52
+#define LOCAL_GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
+#define LOCAL_GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define LOCAL_GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
+#define LOCAL_GL_RENDERBUFFER_DEPTH_SIZE_OES 0x8D54
+#define LOCAL_GL_RENDERBUFFER_EXT 0x8D41
+#define LOCAL_GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
+#define LOCAL_GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define LOCAL_GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
+#define LOCAL_GL_RENDERBUFFER_GREEN_SIZE_OES 0x8D51
+#define LOCAL_GL_RENDERBUFFER_HEIGHT 0x8D43
+#define LOCAL_GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
+#define LOCAL_GL_RENDERBUFFER_HEIGHT_OES 0x8D43
+#define LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
+#define LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44
+#define LOCAL_GL_RENDERBUFFER_OES 0x8D41
+#define LOCAL_GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define LOCAL_GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
+#define LOCAL_GL_RENDERBUFFER_RED_SIZE_OES 0x8D50
+#define LOCAL_GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_SAMPLES_IMG 0x9133
+#define LOCAL_GL_RENDERBUFFER_SAMPLES_NV 0x8CAB
+#define LOCAL_GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define LOCAL_GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
+#define LOCAL_GL_RENDERBUFFER_STENCIL_SIZE_OES 0x8D55
+#define LOCAL_GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2
+#define LOCAL_GL_RENDERBUFFER_WIDTH 0x8D42
+#define LOCAL_GL_RENDERBUFFER_WIDTH_EXT 0x8D42
+#define LOCAL_GL_RENDERBUFFER_WIDTH_OES 0x8D42
+#define LOCAL_GL_RENDERER 0x1F01
+#define LOCAL_GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3
+#define LOCAL_GL_RENDER_GPU_MASK_NV 0x9558
+#define LOCAL_GL_RENDER_MODE 0x0C40
+#define LOCAL_GL_REPEAT 0x2901
+#define LOCAL_GL_REPLACE 0x1E01
+#define LOCAL_GL_REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3
+#define LOCAL_GL_REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2
+#define LOCAL_GL_REPLACEMENT_CODE_ARRAY_SUN 0x85C0
+#define LOCAL_GL_REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1
+#define LOCAL_GL_REPLACEMENT_CODE_SUN 0x81D8
+#define LOCAL_GL_REPLACE_EXT 0x8062
+#define LOCAL_GL_REPLACE_MIDDLE_SUN 0x0002
+#define LOCAL_GL_REPLACE_OLDEST_SUN 0x0003
+#define LOCAL_GL_REPLACE_VALUE_AMD 0x874B
+#define LOCAL_GL_REPLICATE_BORDER 0x8153
+#define LOCAL_GL_REPLICATE_BORDER_HP 0x8153
+#define LOCAL_GL_REPRESENTATIVE_FRAGMENT_TEST_NV 0x937F
+#define LOCAL_GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68
+#define LOCAL_GL_RESAMPLE_AVERAGE_OML 0x8988
+#define LOCAL_GL_RESAMPLE_DECIMATE_OML 0x8989
+#define LOCAL_GL_RESAMPLE_DECIMATE_SGIX 0x8430
+#define LOCAL_GL_RESAMPLE_REPLICATE_OML 0x8986
+#define LOCAL_GL_RESAMPLE_REPLICATE_SGIX 0x8433
+#define LOCAL_GL_RESAMPLE_ZERO_FILL_OML 0x8987
+#define LOCAL_GL_RESAMPLE_ZERO_FILL_SGIX 0x8434
+#define LOCAL_GL_RESCALE_NORMAL 0x803A
+#define LOCAL_GL_RESCALE_NORMAL_EXT 0x803A
+#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256
+#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define LOCAL_GL_RESTART_PATH_NV 0xF0
+#define LOCAL_GL_RESTART_SUN 0x0001
+#define LOCAL_GL_RETAINED_APPLE 0x8A1B
+#define LOCAL_GL_RETURN 0x0102
+#define LOCAL_GL_RG 0x8227
+#define LOCAL_GL_RG16 0x822C
+#define LOCAL_GL_RG16F 0x822F
+#define LOCAL_GL_RG16F_EXT 0x822F
+#define LOCAL_GL_RG16I 0x8239
+#define LOCAL_GL_RG16UI 0x823A
+#define LOCAL_GL_RG16_EXT 0x822C
+#define LOCAL_GL_RG16_SNORM 0x8F99
+#define LOCAL_GL_RG16_SNORM_EXT 0x8F99
+#define LOCAL_GL_RG32F 0x8230
+#define LOCAL_GL_RG32F_EXT 0x8230
+#define LOCAL_GL_RG32I 0x823B
+#define LOCAL_GL_RG32UI 0x823C
+#define LOCAL_GL_RG8 0x822B
+#define LOCAL_GL_RG8I 0x8237
+#define LOCAL_GL_RG8UI 0x8238
+#define LOCAL_GL_RG8_EXT 0x822B
+#define LOCAL_GL_RG8_SNORM 0x8F95
+#define LOCAL_GL_RGB 0x1907
+#define LOCAL_GL_RGB10 0x8052
+#define LOCAL_GL_RGB10_A2 0x8059
+#define LOCAL_GL_RGB10_A2UI 0x906F
+#define LOCAL_GL_RGB10_A2_EXT 0x8059
+#define LOCAL_GL_RGB10_EXT 0x8052
+#define LOCAL_GL_RGB12 0x8053
+#define LOCAL_GL_RGB12_EXT 0x8053
+#define LOCAL_GL_RGB16 0x8054
+#define LOCAL_GL_RGB16F 0x881B
+#define LOCAL_GL_RGB16F_ARB 0x881B
+#define LOCAL_GL_RGB16F_EXT 0x881B
+#define LOCAL_GL_RGB16I 0x8D89
+#define LOCAL_GL_RGB16I_EXT 0x8D89
+#define LOCAL_GL_RGB16UI 0x8D77
+#define LOCAL_GL_RGB16UI_EXT 0x8D77
+#define LOCAL_GL_RGB16_EXT 0x8054
+#define LOCAL_GL_RGB16_SNORM 0x8F9A
+#define LOCAL_GL_RGB16_SNORM_EXT 0x8F9A
+#define LOCAL_GL_RGB2_EXT 0x804E
+#define LOCAL_GL_RGB32F 0x8815
+#define LOCAL_GL_RGB32F_ARB 0x8815
+#define LOCAL_GL_RGB32F_EXT 0x8815
+#define LOCAL_GL_RGB32I 0x8D83
+#define LOCAL_GL_RGB32I_EXT 0x8D83
+#define LOCAL_GL_RGB32UI 0x8D71
+#define LOCAL_GL_RGB32UI_EXT 0x8D71
+#define LOCAL_GL_RGB4 0x804F
+#define LOCAL_GL_RGB4_EXT 0x804F
+#define LOCAL_GL_RGB4_S3TC 0x83A1
+#define LOCAL_GL_RGB5 0x8050
+#define LOCAL_GL_RGB565 0x8D62
+#define LOCAL_GL_RGB565_OES 0x8D62
+#define LOCAL_GL_RGB5_A1 0x8057
+#define LOCAL_GL_RGB5_A1_EXT 0x8057
+#define LOCAL_GL_RGB5_A1_OES 0x8057
+#define LOCAL_GL_RGB5_EXT 0x8050
+#define LOCAL_GL_RGB8 0x8051
+#define LOCAL_GL_RGB8I 0x8D8F
+#define LOCAL_GL_RGB8I_EXT 0x8D8F
+#define LOCAL_GL_RGB8UI 0x8D7D
+#define LOCAL_GL_RGB8UI_EXT 0x8D7D
+#define LOCAL_GL_RGB8_EXT 0x8051
+#define LOCAL_GL_RGB8_OES 0x8051
+#define LOCAL_GL_RGB8_SNORM 0x8F96
+#define LOCAL_GL_RGB9_E5 0x8C3D
+#define LOCAL_GL_RGB9_E5_APPLE 0x8C3D
+#define LOCAL_GL_RGB9_E5_EXT 0x8C3D
+#define LOCAL_GL_RGBA 0x1908
+#define LOCAL_GL_RGBA12 0x805A
+#define LOCAL_GL_RGBA12_EXT 0x805A
+#define LOCAL_GL_RGBA16 0x805B
+#define LOCAL_GL_RGBA16F 0x881A
+#define LOCAL_GL_RGBA16F_ARB 0x881A
+#define LOCAL_GL_RGBA16F_EXT 0x881A
+#define LOCAL_GL_RGBA16I 0x8D88
+#define LOCAL_GL_RGBA16I_EXT 0x8D88
+#define LOCAL_GL_RGBA16UI 0x8D76
+#define LOCAL_GL_RGBA16UI_EXT 0x8D76
+#define LOCAL_GL_RGBA16_EXT 0x805B
+#define LOCAL_GL_RGBA16_SNORM 0x8F9B
+#define LOCAL_GL_RGBA16_SNORM_EXT 0x8F9B
+#define LOCAL_GL_RGBA2 0x8055
+#define LOCAL_GL_RGBA2_EXT 0x8055
+#define LOCAL_GL_RGBA32F 0x8814
+#define LOCAL_GL_RGBA32F_ARB 0x8814
+#define LOCAL_GL_RGBA32F_EXT 0x8814
+#define LOCAL_GL_RGBA32I 0x8D82
+#define LOCAL_GL_RGBA32I_EXT 0x8D82
+#define LOCAL_GL_RGBA32UI 0x8D70
+#define LOCAL_GL_RGBA32UI_EXT 0x8D70
+#define LOCAL_GL_RGBA4 0x8056
+#define LOCAL_GL_RGBA4_DXT5_S3TC 0x83A5
+#define LOCAL_GL_RGBA4_EXT 0x8056
+#define LOCAL_GL_RGBA4_OES 0x8056
+#define LOCAL_GL_RGBA4_S3TC 0x83A3
+#define LOCAL_GL_RGBA8 0x8058
+#define LOCAL_GL_RGBA8I 0x8D8E
+#define LOCAL_GL_RGBA8I_EXT 0x8D8E
+#define LOCAL_GL_RGBA8UI 0x8D7C
+#define LOCAL_GL_RGBA8UI_EXT 0x8D7C
+#define LOCAL_GL_RGBA8_EXT 0x8058
+#define LOCAL_GL_RGBA8_OES 0x8058
+#define LOCAL_GL_RGBA8_SNORM 0x8F97
+#define LOCAL_GL_RGBA_DXT5_S3TC 0x83A4
+#define LOCAL_GL_RGBA_FLOAT16_APPLE 0x881A
+#define LOCAL_GL_RGBA_FLOAT16_ATI 0x881A
+#define LOCAL_GL_RGBA_FLOAT32_APPLE 0x8814
+#define LOCAL_GL_RGBA_FLOAT32_ATI 0x8814
+#define LOCAL_GL_RGBA_FLOAT_MODE_ARB 0x8820
+#define LOCAL_GL_RGBA_FLOAT_MODE_ATI 0x8820
+#define LOCAL_GL_RGBA_INTEGER 0x8D99
+#define LOCAL_GL_RGBA_INTEGER_EXT 0x8D99
+#define LOCAL_GL_RGBA_INTEGER_MODE_EXT 0x8D9E
+#define LOCAL_GL_RGBA_MODE 0x0C31
+#define LOCAL_GL_RGBA_S3TC 0x83A2
+#define LOCAL_GL_RGBA_SIGNED_COMPONENTS_EXT 0x8C3C
+#define LOCAL_GL_RGBA_SNORM 0x8F93
+#define LOCAL_GL_RGBA_UNSIGNED_DOT_PRODUCT_MAPPING_NV 0x86D9
+#define LOCAL_GL_RGB_422_APPLE 0x8A1F
+#define LOCAL_GL_RGB_FLOAT16_APPLE 0x881B
+#define LOCAL_GL_RGB_FLOAT16_ATI 0x881B
+#define LOCAL_GL_RGB_FLOAT32_APPLE 0x8815
+#define LOCAL_GL_RGB_FLOAT32_ATI 0x8815
+#define LOCAL_GL_RGB_INTEGER 0x8D98
+#define LOCAL_GL_RGB_INTEGER_EXT 0x8D98
+#define LOCAL_GL_RGB_RAW_422_APPLE 0x8A51
+#define LOCAL_GL_RGB_S3TC 0x83A0
+#define LOCAL_GL_RGB_SCALE 0x8573
+#define LOCAL_GL_RGB_SCALE_ARB 0x8573
+#define LOCAL_GL_RGB_SCALE_EXT 0x8573
+#define LOCAL_GL_RGB_SNORM 0x8F92
+#define LOCAL_GL_RG_EXT 0x8227
+#define LOCAL_GL_RG_INTEGER 0x8228
+#define LOCAL_GL_RG_SNORM 0x8F91
+#define LOCAL_GL_RIGHT 0x0407
+#define LOCAL_GL_ROBUST_GPU_TIMEOUT_MS_KHR 0x82FD
+#define LOCAL_GL_ROUNDED_RECT2_NV 0xEA
+#define LOCAL_GL_ROUNDED_RECT4_NV 0xEC
+#define LOCAL_GL_ROUNDED_RECT8_NV 0xEE
+#define LOCAL_GL_ROUNDED_RECT_NV 0xE8
+#define LOCAL_GL_ROUND_NV 0x90A4
+#define LOCAL_GL_S 0x2000
+#define LOCAL_GL_SAMPLER 0x82E6
+#define LOCAL_GL_SAMPLER_1D 0x8B5D
+#define LOCAL_GL_SAMPLER_1D_ARB 0x8B5D
+#define LOCAL_GL_SAMPLER_1D_ARRAY 0x8DC0
+#define LOCAL_GL_SAMPLER_1D_ARRAY_EXT 0x8DC0
+#define LOCAL_GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define LOCAL_GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3
+#define LOCAL_GL_SAMPLER_1D_SHADOW 0x8B61
+#define LOCAL_GL_SAMPLER_1D_SHADOW_ARB 0x8B61
+#define LOCAL_GL_SAMPLER_2D 0x8B5E
+#define LOCAL_GL_SAMPLER_2D_ARB 0x8B5E
+#define LOCAL_GL_SAMPLER_2D_ARRAY 0x8DC1
+#define LOCAL_GL_SAMPLER_2D_ARRAY_EXT 0x8DC1
+#define LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4
+#define LOCAL_GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4
+#define LOCAL_GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define LOCAL_GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define LOCAL_GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B
+#define LOCAL_GL_SAMPLER_2D_RECT 0x8B63
+#define LOCAL_GL_SAMPLER_2D_RECT_ARB 0x8B63
+#define LOCAL_GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define LOCAL_GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64
+#define LOCAL_GL_SAMPLER_2D_SHADOW 0x8B62
+#define LOCAL_GL_SAMPLER_2D_SHADOW_ARB 0x8B62
+#define LOCAL_GL_SAMPLER_2D_SHADOW_EXT 0x8B62
+#define LOCAL_GL_SAMPLER_3D 0x8B5F
+#define LOCAL_GL_SAMPLER_3D_ARB 0x8B5F
+#define LOCAL_GL_SAMPLER_3D_OES 0x8B5F
+#define LOCAL_GL_SAMPLER_BINDING 0x8919
+#define LOCAL_GL_SAMPLER_BUFFER 0x8DC2
+#define LOCAL_GL_SAMPLER_BUFFER_AMD 0x9001
+#define LOCAL_GL_SAMPLER_BUFFER_EXT 0x8DC2
+#define LOCAL_GL_SAMPLER_BUFFER_OES 0x8DC2
+#define LOCAL_GL_SAMPLER_CUBE 0x8B60
+#define LOCAL_GL_SAMPLER_CUBE_ARB 0x8B60
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_OES 0x900C
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D
+#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define LOCAL_GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define LOCAL_GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5
+#define LOCAL_GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5
+#define LOCAL_GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT 0x8BE7
+#define LOCAL_GL_SAMPLER_EXTERNAL_OES 0x8D66
+#define LOCAL_GL_SAMPLER_KHR 0x82E6
+#define LOCAL_GL_SAMPLER_OBJECT_AMD 0x9155
+#define LOCAL_GL_SAMPLER_RENDERBUFFER_NV 0x8E56
+#define LOCAL_GL_SAMPLES 0x80A9
+#define LOCAL_GL_SAMPLES_3DFX 0x86B4
+#define LOCAL_GL_SAMPLES_ARB 0x80A9
+#define LOCAL_GL_SAMPLES_EXT 0x80A9
+#define LOCAL_GL_SAMPLES_PASSED 0x8914
+#define LOCAL_GL_SAMPLES_PASSED_ARB 0x8914
+#define LOCAL_GL_SAMPLES_SGIS 0x80A9
+#define LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define LOCAL_GL_SAMPLE_ALPHA_TO_MASK_EXT 0x809E
+#define LOCAL_GL_SAMPLE_ALPHA_TO_MASK_SGIS 0x809E
+#define LOCAL_GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define LOCAL_GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define LOCAL_GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#define LOCAL_GL_SAMPLE_ALPHA_TO_ONE_SGIS 0x809F
+#define LOCAL_GL_SAMPLE_BUFFERS 0x80A8
+#define LOCAL_GL_SAMPLE_BUFFERS_3DFX 0x86B3
+#define LOCAL_GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define LOCAL_GL_SAMPLE_BUFFERS_EXT 0x80A8
+#define LOCAL_GL_SAMPLE_BUFFERS_SGIS 0x80A8
+#define LOCAL_GL_SAMPLE_COVERAGE 0x80A0
+#define LOCAL_GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define LOCAL_GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define LOCAL_GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define LOCAL_GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define LOCAL_GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define LOCAL_GL_SAMPLE_LOCATION_ARB 0x8E50
+#define LOCAL_GL_SAMPLE_LOCATION_NV 0x8E50
+#define LOCAL_GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F
+#define LOCAL_GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define LOCAL_GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E
+#define LOCAL_GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define LOCAL_GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D
+#define LOCAL_GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define LOCAL_GL_SAMPLE_MASK 0x8E51
+#define LOCAL_GL_SAMPLE_MASK_EXT 0x80A0
+#define LOCAL_GL_SAMPLE_MASK_INVERT_EXT 0x80AB
+#define LOCAL_GL_SAMPLE_MASK_INVERT_SGIS 0x80AB
+#define LOCAL_GL_SAMPLE_MASK_NV 0x8E51
+#define LOCAL_GL_SAMPLE_MASK_SGIS 0x80A0
+#define LOCAL_GL_SAMPLE_MASK_VALUE 0x8E52
+#define LOCAL_GL_SAMPLE_MASK_VALUE_EXT 0x80AA
+#define LOCAL_GL_SAMPLE_MASK_VALUE_NV 0x8E52
+#define LOCAL_GL_SAMPLE_MASK_VALUE_SGIS 0x80AA
+#define LOCAL_GL_SAMPLE_PATTERN_EXT 0x80AC
+#define LOCAL_GL_SAMPLE_PATTERN_SGIS 0x80AC
+#define LOCAL_GL_SAMPLE_POSITION 0x8E50
+#define LOCAL_GL_SAMPLE_POSITION_NV 0x8E50
+#define LOCAL_GL_SAMPLE_SHADING 0x8C36
+#define LOCAL_GL_SAMPLE_SHADING_ARB 0x8C36
+#define LOCAL_GL_SAMPLE_SHADING_OES 0x8C36
+#define LOCAL_GL_SATURATE_BIT_ATI 0x00000040
+#define LOCAL_GL_SCALAR_EXT 0x87BE
+#define LOCAL_GL_SCALEBIAS_HINT_SGIX 0x8322
+#define LOCAL_GL_SCALED_RESOLVE_FASTEST_EXT 0x90BA
+#define LOCAL_GL_SCALED_RESOLVE_NICEST_EXT 0x90BB
+#define LOCAL_GL_SCALE_BY_FOUR_NV 0x853F
+#define LOCAL_GL_SCALE_BY_ONE_HALF_NV 0x8540
+#define LOCAL_GL_SCALE_BY_TWO_NV 0x853E
+#define LOCAL_GL_SCISSOR_BIT 0x00080000
+#define LOCAL_GL_SCISSOR_BOX 0x0C10
+#define LOCAL_GL_SCISSOR_BOX_EXCLUSIVE_NV 0x9556
+#define LOCAL_GL_SCISSOR_COMMAND_NV 0x0011
+#define LOCAL_GL_SCISSOR_TEST 0x0C11
+#define LOCAL_GL_SCISSOR_TEST_EXCLUSIVE_NV 0x9555
+#define LOCAL_GL_SCREEN 0x9295
+#define LOCAL_GL_SCREEN_COORDINATES_REND 0x8490
+#define LOCAL_GL_SCREEN_KHR 0x9295
+#define LOCAL_GL_SCREEN_NV 0x9295
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY 0x845E
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_ADDRESS_NV 0x8F27
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_EXT 0x845E
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_LENGTH_NV 0x8F31
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_LIST_IBM 103077
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_LIST_STRIDE_IBM 103087
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_SIZE_EXT 0x845A
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT 0x845C
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define LOCAL_GL_SECONDARY_COLOR_ARRAY_TYPE_EXT 0x845B
+#define LOCAL_GL_SECONDARY_COLOR_NV 0x852D
+#define LOCAL_GL_SECONDARY_INTERPOLATOR_ATI 0x896D
+#define LOCAL_GL_SELECT 0x1C02
+#define LOCAL_GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define LOCAL_GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define LOCAL_GL_SEMAPHORE_TYPE_BINARY_NV 0x95B4
+#define LOCAL_GL_SEMAPHORE_TYPE_NV 0x95B3
+#define LOCAL_GL_SEMAPHORE_TYPE_TIMELINE_NV 0x95B5
+#define LOCAL_GL_SEPARABLE_2D 0x8012
+#define LOCAL_GL_SEPARABLE_2D_EXT 0x8012
+#define LOCAL_GL_SEPARATE_ATTRIBS 0x8C8D
+#define LOCAL_GL_SEPARATE_ATTRIBS_EXT 0x8C8D
+#define LOCAL_GL_SEPARATE_ATTRIBS_NV 0x8C8D
+#define LOCAL_GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define LOCAL_GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#define LOCAL_GL_SET 0x150F
+#define LOCAL_GL_SET_AMD 0x874A
+#define LOCAL_GL_SGX_BINARY_IMG 0x8C0A
+#define LOCAL_GL_SGX_PROGRAM_BINARY_IMG 0x9130
+#define LOCAL_GL_SHADER 0x82E1
+#define LOCAL_GL_SHADER_BINARY_DMP 0x9250
+#define LOCAL_GL_SHADER_BINARY_FORMATS 0x8DF8
+#define LOCAL_GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551
+#define LOCAL_GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551
+#define LOCAL_GL_SHADER_BINARY_VIV 0x8FC4
+#define LOCAL_GL_SHADER_COMPILER 0x8DFA
+#define LOCAL_GL_SHADER_CONSISTENT_NV 0x86DD
+#define LOCAL_GL_SHADER_GLOBAL_ACCESS_BARRIER_BIT_NV 0x00000010
+#define LOCAL_GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define LOCAL_GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020
+#define LOCAL_GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define LOCAL_GL_SHADER_IMAGE_LOAD 0x82A4
+#define LOCAL_GL_SHADER_IMAGE_STORE 0x82A5
+#define LOCAL_GL_SHADER_INCLUDE_ARB 0x8DAE
+#define LOCAL_GL_SHADER_KHR 0x82E1
+#define LOCAL_GL_SHADER_OBJECT_ARB 0x8B48
+#define LOCAL_GL_SHADER_OBJECT_EXT 0x8B48
+#define LOCAL_GL_SHADER_OPERATION_NV 0x86DF
+#define LOCAL_GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64
+#define LOCAL_GL_SHADER_SOURCE_LENGTH 0x8B88
+#define LOCAL_GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define LOCAL_GL_SHADER_STORAGE_BLOCK 0x92E6
+#define LOCAL_GL_SHADER_STORAGE_BUFFER 0x90D2
+#define LOCAL_GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define LOCAL_GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define LOCAL_GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define LOCAL_GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define LOCAL_GL_SHADER_TYPE 0x8B4F
+#define LOCAL_GL_SHADE_MODEL 0x0B54
+#define LOCAL_GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define LOCAL_GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C
+#define LOCAL_GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV 0x956F
+#define LOCAL_GL_SHADING_RATE_1X1_PIXELS_QCOM 0x96A6
+#define LOCAL_GL_SHADING_RATE_1X2_PIXELS_QCOM 0x96A7
+#define LOCAL_GL_SHADING_RATE_1X4_PIXELS_QCOM 0x96AA
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV 0x9566
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV 0x9567
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV 0x9568
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV 0x9569
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV 0x956A
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV 0x956B
+#define LOCAL_GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV 0x9565
+#define LOCAL_GL_SHADING_RATE_2X1_PIXELS_QCOM 0x96A8
+#define LOCAL_GL_SHADING_RATE_2X2_PIXELS_QCOM 0x96A9
+#define LOCAL_GL_SHADING_RATE_2X4_PIXELS_QCOM 0x96AD
+#define LOCAL_GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV 0x956C
+#define LOCAL_GL_SHADING_RATE_4X1_PIXELS_QCOM 0x96AB
+#define LOCAL_GL_SHADING_RATE_4X2_PIXELS_QCOM 0x96AC
+#define LOCAL_GL_SHADING_RATE_4X4_PIXELS_QCOM 0x96AE
+#define LOCAL_GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV 0x956D
+#define LOCAL_GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV 0x956E
+#define LOCAL_GL_SHADING_RATE_IMAGE_BINDING_NV 0x955B
+#define LOCAL_GL_SHADING_RATE_IMAGE_NV 0x9563
+#define LOCAL_GL_SHADING_RATE_IMAGE_PALETTE_COUNT_NV 0x95B2
+#define LOCAL_GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV 0x955E
+#define LOCAL_GL_SHADING_RATE_IMAGE_PER_PRIMITIVE_NV 0x95B1
+#define LOCAL_GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV 0x955D
+#define LOCAL_GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV 0x955C
+#define LOCAL_GL_SHADING_RATE_NO_INVOCATIONS_NV 0x9564
+#define LOCAL_GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM 0x96A5
+#define LOCAL_GL_SHADING_RATE_QCOM 0x96A4
+#define LOCAL_GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV 0x95AE
+#define LOCAL_GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV 0x95AF
+#define LOCAL_GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV 0x95B0
+#define LOCAL_GL_SHADOW_AMBIENT_SGIX 0x80BF
+#define LOCAL_GL_SHADOW_ATTENUATION_EXT 0x834E
+#define LOCAL_GL_SHARED_EDGE_NV 0xC0
+#define LOCAL_GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
+#define LOCAL_GL_SHARPEN_TEXTURE_FUNC_POINTS_SGIS 0x80B0
+#define LOCAL_GL_SHININESS 0x1601
+#define LOCAL_GL_SHORT 0x1402
+#define LOCAL_GL_SIGNALED 0x9119
+#define LOCAL_GL_SIGNALED_APPLE 0x9119
+#define LOCAL_GL_SIGNED_ALPHA8_NV 0x8706
+#define LOCAL_GL_SIGNED_ALPHA_NV 0x8705
+#define LOCAL_GL_SIGNED_HILO16_NV 0x86FA
+#define LOCAL_GL_SIGNED_HILO8_NV 0x885F
+#define LOCAL_GL_SIGNED_HILO_NV 0x86F9
+#define LOCAL_GL_SIGNED_IDENTITY_NV 0x853C
+#define LOCAL_GL_SIGNED_INTENSITY8_NV 0x8708
+#define LOCAL_GL_SIGNED_INTENSITY_NV 0x8707
+#define LOCAL_GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704
+#define LOCAL_GL_SIGNED_LUMINANCE8_NV 0x8702
+#define LOCAL_GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703
+#define LOCAL_GL_SIGNED_LUMINANCE_NV 0x8701
+#define LOCAL_GL_SIGNED_NEGATE_NV 0x853D
+#define LOCAL_GL_SIGNED_NORMALIZED 0x8F9C
+#define LOCAL_GL_SIGNED_RGB8_NV 0x86FF
+#define LOCAL_GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D
+#define LOCAL_GL_SIGNED_RGBA8_NV 0x86FC
+#define LOCAL_GL_SIGNED_RGBA_NV 0x86FB
+#define LOCAL_GL_SIGNED_RGB_NV 0x86FE
+#define LOCAL_GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C
+#define LOCAL_GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define LOCAL_GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define LOCAL_GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define LOCAL_GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define LOCAL_GL_SINGLE_COLOR 0x81F9
+#define LOCAL_GL_SINGLE_COLOR_EXT 0x81F9
+#define LOCAL_GL_SKIP_COMPONENTS1_NV -6
+#define LOCAL_GL_SKIP_COMPONENTS2_NV -5
+#define LOCAL_GL_SKIP_COMPONENTS3_NV -4
+#define LOCAL_GL_SKIP_COMPONENTS4_NV -3
+#define LOCAL_GL_SKIP_DECODE_EXT 0x8A4A
+#define LOCAL_GL_SKIP_MISSING_GLYPH_NV 0x90A9
+#define LOCAL_GL_SLICE_ACCUM_SUN 0x85CC
+#define LOCAL_GL_SLIM10U_SGIX 0x831E
+#define LOCAL_GL_SLIM12S_SGIX 0x831F
+#define LOCAL_GL_SLIM8U_SGIX 0x831D
+#define LOCAL_GL_SLUMINANCE 0x8C46
+#define LOCAL_GL_SLUMINANCE8 0x8C47
+#define LOCAL_GL_SLUMINANCE8_ALPHA8 0x8C45
+#define LOCAL_GL_SLUMINANCE8_ALPHA8_EXT 0x8C45
+#define LOCAL_GL_SLUMINANCE8_ALPHA8_NV 0x8C45
+#define LOCAL_GL_SLUMINANCE8_EXT 0x8C47
+#define LOCAL_GL_SLUMINANCE8_NV 0x8C47
+#define LOCAL_GL_SLUMINANCE_ALPHA 0x8C44
+#define LOCAL_GL_SLUMINANCE_ALPHA_EXT 0x8C44
+#define LOCAL_GL_SLUMINANCE_ALPHA_NV 0x8C44
+#define LOCAL_GL_SLUMINANCE_EXT 0x8C46
+#define LOCAL_GL_SLUMINANCE_NV 0x8C46
+#define LOCAL_GL_SMALL_CCW_ARC_TO_NV 0x12
+#define LOCAL_GL_SMALL_CW_ARC_TO_NV 0x14
+#define LOCAL_GL_SMAPHS30_PROGRAM_BINARY_DMP 0x9251
+#define LOCAL_GL_SMAPHS_PROGRAM_BINARY_DMP 0x9252
+#define LOCAL_GL_SMOOTH 0x1D01
+#define LOCAL_GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10
+#define LOCAL_GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define LOCAL_GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define LOCAL_GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define LOCAL_GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define LOCAL_GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E
+#define LOCAL_GL_SM_COUNT_NV 0x933B
+#define LOCAL_GL_SOFTLIGHT 0x929C
+#define LOCAL_GL_SOFTLIGHT_KHR 0x929C
+#define LOCAL_GL_SOFTLIGHT_NV 0x929C
+#define LOCAL_GL_SOURCE0_ALPHA 0x8588
+#define LOCAL_GL_SOURCE0_ALPHA_ARB 0x8588
+#define LOCAL_GL_SOURCE0_ALPHA_EXT 0x8588
+#define LOCAL_GL_SOURCE0_RGB 0x8580
+#define LOCAL_GL_SOURCE0_RGB_ARB 0x8580
+#define LOCAL_GL_SOURCE0_RGB_EXT 0x8580
+#define LOCAL_GL_SOURCE1_ALPHA 0x8589
+#define LOCAL_GL_SOURCE1_ALPHA_ARB 0x8589
+#define LOCAL_GL_SOURCE1_ALPHA_EXT 0x8589
+#define LOCAL_GL_SOURCE1_RGB 0x8581
+#define LOCAL_GL_SOURCE1_RGB_ARB 0x8581
+#define LOCAL_GL_SOURCE1_RGB_EXT 0x8581
+#define LOCAL_GL_SOURCE2_ALPHA 0x858A
+#define LOCAL_GL_SOURCE2_ALPHA_ARB 0x858A
+#define LOCAL_GL_SOURCE2_ALPHA_EXT 0x858A
+#define LOCAL_GL_SOURCE2_RGB 0x8582
+#define LOCAL_GL_SOURCE2_RGB_ARB 0x8582
+#define LOCAL_GL_SOURCE2_RGB_EXT 0x8582
+#define LOCAL_GL_SOURCE3_ALPHA_NV 0x858B
+#define LOCAL_GL_SOURCE3_RGB_NV 0x8583
+#define LOCAL_GL_SPARE0_NV 0x852E
+#define LOCAL_GL_SPARE0_PLUS_SECONDARY_COLOR_NV 0x8532
+#define LOCAL_GL_SPARE1_NV 0x852F
+#define LOCAL_GL_SPARSE_BUFFER_PAGE_SIZE_ARB 0x82F8
+#define LOCAL_GL_SPARSE_STORAGE_BIT_ARB 0x0400
+#define LOCAL_GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9
+#define LOCAL_GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+#define LOCAL_GL_SPECULAR 0x1202
+#define LOCAL_GL_SPHERE_MAP 0x2402
+#define LOCAL_GL_SPIR_V_BINARY 0x9552
+#define LOCAL_GL_SPIR_V_BINARY_ARB 0x9552
+#define LOCAL_GL_SPIR_V_EXTENSIONS 0x9553
+#define LOCAL_GL_SPOT_CUTOFF 0x1206
+#define LOCAL_GL_SPOT_DIRECTION 0x1204
+#define LOCAL_GL_SPOT_EXPONENT 0x1205
+#define LOCAL_GL_SPRITE_AXIAL_SGIX 0x814C
+#define LOCAL_GL_SPRITE_AXIS_SGIX 0x814A
+#define LOCAL_GL_SPRITE_EYE_ALIGNED_SGIX 0x814E
+#define LOCAL_GL_SPRITE_MODE_SGIX 0x8149
+#define LOCAL_GL_SPRITE_OBJECT_ALIGNED_SGIX 0x814D
+#define LOCAL_GL_SPRITE_SGIX 0x8148
+#define LOCAL_GL_SPRITE_TRANSLATION_SGIX 0x814B
+#define LOCAL_GL_SQUARE_NV 0x90A3
+#define LOCAL_GL_SR8_EXT 0x8FBD
+#define LOCAL_GL_SRC0_ALPHA 0x8588
+#define LOCAL_GL_SRC0_RGB 0x8580
+#define LOCAL_GL_SRC1_ALPHA 0x8589
+#define LOCAL_GL_SRC1_ALPHA_EXT 0x8589
+#define LOCAL_GL_SRC1_COLOR 0x88F9
+#define LOCAL_GL_SRC1_COLOR_EXT 0x88F9
+#define LOCAL_GL_SRC1_RGB 0x8581
+#define LOCAL_GL_SRC2_ALPHA 0x858A
+#define LOCAL_GL_SRC2_RGB 0x8582
+#define LOCAL_GL_SRC_ALPHA 0x0302
+#define LOCAL_GL_SRC_ALPHA_SATURATE 0x0308
+#define LOCAL_GL_SRC_ALPHA_SATURATE_EXT 0x0308
+#define LOCAL_GL_SRC_ATOP_NV 0x928E
+#define LOCAL_GL_SRC_COLOR 0x0300
+#define LOCAL_GL_SRC_IN_NV 0x928A
+#define LOCAL_GL_SRC_NV 0x9286
+#define LOCAL_GL_SRC_OUT_NV 0x928C
+#define LOCAL_GL_SRC_OVER_NV 0x9288
+#define LOCAL_GL_SRG8_EXT 0x8FBE
+#define LOCAL_GL_SRGB 0x8C40
+#define LOCAL_GL_SRGB8 0x8C41
+#define LOCAL_GL_SRGB8_ALPHA8 0x8C43
+#define LOCAL_GL_SRGB8_ALPHA8_EXT 0x8C43
+#define LOCAL_GL_SRGB8_EXT 0x8C41
+#define LOCAL_GL_SRGB8_NV 0x8C41
+#define LOCAL_GL_SRGB_ALPHA 0x8C42
+#define LOCAL_GL_SRGB_ALPHA_EXT 0x8C42
+#define LOCAL_GL_SRGB_DECODE_ARB 0x8299
+#define LOCAL_GL_SRGB_EXT 0x8C40
+#define LOCAL_GL_SRGB_READ 0x8297
+#define LOCAL_GL_SRGB_WRITE 0x8298
+#define LOCAL_GL_STACK_OVERFLOW 0x0503
+#define LOCAL_GL_STACK_OVERFLOW_KHR 0x0503
+#define LOCAL_GL_STACK_UNDERFLOW 0x0504
+#define LOCAL_GL_STACK_UNDERFLOW_KHR 0x0504
+#define LOCAL_GL_STANDARD_FONT_FORMAT_NV 0x936C
+#define LOCAL_GL_STANDARD_FONT_NAME_NV 0x9072
+#define LOCAL_GL_STATE_RESTORE 0x8BDC
+#define LOCAL_GL_STATIC_ATI 0x8760
+#define LOCAL_GL_STATIC_COPY 0x88E6
+#define LOCAL_GL_STATIC_COPY_ARB 0x88E6
+#define LOCAL_GL_STATIC_DRAW 0x88E4
+#define LOCAL_GL_STATIC_DRAW_ARB 0x88E4
+#define LOCAL_GL_STATIC_READ 0x88E5
+#define LOCAL_GL_STATIC_READ_ARB 0x88E5
+#define LOCAL_GL_STATIC_VERTEX_ARRAY_IBM 103061
+#define LOCAL_GL_STENCIL 0x1802
+#define LOCAL_GL_STENCIL_ATTACHMENT 0x8D20
+#define LOCAL_GL_STENCIL_ATTACHMENT_EXT 0x8D20
+#define LOCAL_GL_STENCIL_ATTACHMENT_OES 0x8D20
+#define LOCAL_GL_STENCIL_BACK_FAIL 0x8801
+#define LOCAL_GL_STENCIL_BACK_FAIL_ATI 0x8801
+#define LOCAL_GL_STENCIL_BACK_FUNC 0x8800
+#define LOCAL_GL_STENCIL_BACK_FUNC_ATI 0x8800
+#define LOCAL_GL_STENCIL_BACK_OP_VALUE_AMD 0x874D
+#define LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define LOCAL_GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
+#define LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define LOCAL_GL_STENCIL_BACK_PASS_DEPTH_PASS_ATI 0x8803
+#define LOCAL_GL_STENCIL_BACK_REF 0x8CA3
+#define LOCAL_GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define LOCAL_GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define LOCAL_GL_STENCIL_BITS 0x0D57
+#define LOCAL_GL_STENCIL_BUFFER_BIT 0x00000400
+#define LOCAL_GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000
+#define LOCAL_GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000
+#define LOCAL_GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000
+#define LOCAL_GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000
+#define LOCAL_GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000
+#define LOCAL_GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000
+#define LOCAL_GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000
+#define LOCAL_GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000
+#define LOCAL_GL_STENCIL_CLEAR_TAG_VALUE_EXT 0x88F3
+#define LOCAL_GL_STENCIL_CLEAR_VALUE 0x0B91
+#define LOCAL_GL_STENCIL_COMPONENTS 0x8285
+#define LOCAL_GL_STENCIL_EXT 0x1802
+#define LOCAL_GL_STENCIL_FAIL 0x0B94
+#define LOCAL_GL_STENCIL_FUNC 0x0B92
+#define LOCAL_GL_STENCIL_INDEX 0x1901
+#define LOCAL_GL_STENCIL_INDEX1 0x8D46
+#define LOCAL_GL_STENCIL_INDEX16 0x8D49
+#define LOCAL_GL_STENCIL_INDEX16_EXT 0x8D49
+#define LOCAL_GL_STENCIL_INDEX1_EXT 0x8D46
+#define LOCAL_GL_STENCIL_INDEX1_OES 0x8D46
+#define LOCAL_GL_STENCIL_INDEX4 0x8D47
+#define LOCAL_GL_STENCIL_INDEX4_EXT 0x8D47
+#define LOCAL_GL_STENCIL_INDEX4_OES 0x8D47
+#define LOCAL_GL_STENCIL_INDEX8 0x8D48
+#define LOCAL_GL_STENCIL_INDEX8_EXT 0x8D48
+#define LOCAL_GL_STENCIL_INDEX8_OES 0x8D48
+#define LOCAL_GL_STENCIL_INDEX_OES 0x1901
+#define LOCAL_GL_STENCIL_OP_VALUE_AMD 0x874C
+#define LOCAL_GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define LOCAL_GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define LOCAL_GL_STENCIL_REF 0x0B97
+#define LOCAL_GL_STENCIL_REF_COMMAND_NV 0x000C
+#define LOCAL_GL_STENCIL_RENDERABLE 0x8288
+#define LOCAL_GL_STENCIL_SAMPLES_NV 0x932E
+#define LOCAL_GL_STENCIL_TAG_BITS_EXT 0x88F2
+#define LOCAL_GL_STENCIL_TEST 0x0B90
+#define LOCAL_GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
+#define LOCAL_GL_STENCIL_VALUE_MASK 0x0B93
+#define LOCAL_GL_STENCIL_WRITEMASK 0x0B98
+#define LOCAL_GL_STEREO 0x0C33
+#define LOCAL_GL_STORAGE_CACHED_APPLE 0x85BE
+#define LOCAL_GL_STORAGE_CLIENT_APPLE 0x85B4
+#define LOCAL_GL_STORAGE_PRIVATE_APPLE 0x85BD
+#define LOCAL_GL_STORAGE_SHARED_APPLE 0x85BF
+#define LOCAL_GL_STREAM_COPY 0x88E2
+#define LOCAL_GL_STREAM_COPY_ARB 0x88E2
+#define LOCAL_GL_STREAM_DRAW 0x88E0
+#define LOCAL_GL_STREAM_DRAW_ARB 0x88E0
+#define LOCAL_GL_STREAM_RASTERIZATION_AMD 0x91A0
+#define LOCAL_GL_STREAM_READ 0x88E1
+#define LOCAL_GL_STREAM_READ_ARB 0x88E1
+#define LOCAL_GL_STRICT_DEPTHFUNC_HINT_PGI 0x1A216
+#define LOCAL_GL_STRICT_LIGHTING_HINT_PGI 0x1A217
+#define LOCAL_GL_STRICT_SCISSOR_HINT_PGI 0x1A218
+#define LOCAL_GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004
+#define LOCAL_GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008
+#define LOCAL_GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001
+#define LOCAL_GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040
+#define LOCAL_GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV 0x00000100
+#define LOCAL_GL_SUBGROUP_FEATURE_QUAD_BIT_KHR 0x00000080
+#define LOCAL_GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010
+#define LOCAL_GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020
+#define LOCAL_GL_SUBGROUP_FEATURE_VOTE_BIT_KHR 0x00000002
+#define LOCAL_GL_SUBGROUP_QUAD_ALL_STAGES_KHR 0x9535
+#define LOCAL_GL_SUBGROUP_SIZE_KHR 0x9532
+#define LOCAL_GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534
+#define LOCAL_GL_SUBGROUP_SUPPORTED_STAGES_KHR 0x9533
+#define LOCAL_GL_SUBPIXEL_BITS 0x0D50
+#define LOCAL_GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define LOCAL_GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define LOCAL_GL_SUBSAMPLE_DISTANCE_AMD 0x883F
+#define LOCAL_GL_SUBTRACT 0x84E7
+#define LOCAL_GL_SUBTRACT_ARB 0x84E7
+#define LOCAL_GL_SUB_ATI 0x8965
+#define LOCAL_GL_SUCCESS_NV 0x902F
+#define LOCAL_GL_SUPERSAMPLE_SCALE_X_NV 0x9372
+#define LOCAL_GL_SUPERSAMPLE_SCALE_Y_NV 0x9373
+#define LOCAL_GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7
+#define LOCAL_GL_SURFACE_MAPPED_NV 0x8700
+#define LOCAL_GL_SURFACE_REGISTERED_NV 0x86FD
+#define LOCAL_GL_SURFACE_STATE_NV 0x86EB
+#define LOCAL_GL_SWIZZLE_STQ_ATI 0x8977
+#define LOCAL_GL_SWIZZLE_STQ_DQ_ATI 0x8979
+#define LOCAL_GL_SWIZZLE_STRQ_ATI 0x897A
+#define LOCAL_GL_SWIZZLE_STRQ_DQ_ATI 0x897B
+#define LOCAL_GL_SWIZZLE_STR_ATI 0x8976
+#define LOCAL_GL_SWIZZLE_STR_DR_ATI 0x8978
+#define LOCAL_GL_SYNC_CL_EVENT_ARB 0x8240
+#define LOCAL_GL_SYNC_CL_EVENT_COMPLETE_ARB 0x8241
+#define LOCAL_GL_SYNC_CONDITION 0x9113
+#define LOCAL_GL_SYNC_CONDITION_APPLE 0x9113
+#define LOCAL_GL_SYNC_FENCE 0x9116
+#define LOCAL_GL_SYNC_FENCE_APPLE 0x9116
+#define LOCAL_GL_SYNC_FLAGS 0x9115
+#define LOCAL_GL_SYNC_FLAGS_APPLE 0x9115
+#define LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define LOCAL_GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001
+#define LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117
+#define LOCAL_GL_SYNC_OBJECT_APPLE 0x8A53
+#define LOCAL_GL_SYNC_STATUS 0x9114
+#define LOCAL_GL_SYNC_STATUS_APPLE 0x9114
+#define LOCAL_GL_SYNC_X11_FENCE_EXT 0x90E1
+#define LOCAL_GL_SYSTEM_FONT_NAME_NV 0x9073
+#define LOCAL_GL_T 0x2001
+#define LOCAL_GL_T2F_C3F_V3F 0x2A2A
+#define LOCAL_GL_T2F_C4F_N3F_V3F 0x2A2C
+#define LOCAL_GL_T2F_C4UB_V3F 0x2A29
+#define LOCAL_GL_T2F_IUI_N3F_V2F_EXT 0x81B3
+#define LOCAL_GL_T2F_IUI_N3F_V3F_EXT 0x81B4
+#define LOCAL_GL_T2F_IUI_V2F_EXT 0x81B1
+#define LOCAL_GL_T2F_IUI_V3F_EXT 0x81B2
+#define LOCAL_GL_T2F_N3F_V3F 0x2A2B
+#define LOCAL_GL_T2F_V3F 0x2A27
+#define LOCAL_GL_T4F_C4F_N3F_V4F 0x2A2D
+#define LOCAL_GL_T4F_V4F 0x2A28
+#define LOCAL_GL_TABLE_TOO_LARGE 0x8031
+#define LOCAL_GL_TABLE_TOO_LARGE_EXT 0x8031
+#define LOCAL_GL_TANGENT_ARRAY_EXT 0x8439
+#define LOCAL_GL_TANGENT_ARRAY_POINTER_EXT 0x8442
+#define LOCAL_GL_TANGENT_ARRAY_STRIDE_EXT 0x843F
+#define LOCAL_GL_TANGENT_ARRAY_TYPE_EXT 0x843E
+#define LOCAL_GL_TASK_SHADER_BIT_NV 0x00000080
+#define LOCAL_GL_TASK_SHADER_NV 0x955A
+#define LOCAL_GL_TASK_SUBROUTINE_NV 0x957D
+#define LOCAL_GL_TASK_SUBROUTINE_UNIFORM_NV 0x957F
+#define LOCAL_GL_TASK_WORK_GROUP_SIZE_NV 0x953F
+#define LOCAL_GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000
+#define LOCAL_GL_TESSELLATION_FACTOR_AMD 0x9005
+#define LOCAL_GL_TESSELLATION_MODE_AMD 0x9004
+#define LOCAL_GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define LOCAL_GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75
+#define LOCAL_GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define LOCAL_GL_TESS_CONTROL_PROGRAM_NV 0x891E
+#define LOCAL_GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV 0x8C74
+#define LOCAL_GL_TESS_CONTROL_SHADER 0x8E88
+#define LOCAL_GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define LOCAL_GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008
+#define LOCAL_GL_TESS_CONTROL_SHADER_BIT_OES 0x00000008
+#define LOCAL_GL_TESS_CONTROL_SHADER_EXT 0x8E88
+#define LOCAL_GL_TESS_CONTROL_SHADER_OES 0x8E88
+#define LOCAL_GL_TESS_CONTROL_SHADER_PATCHES 0x82F1
+#define LOCAL_GL_TESS_CONTROL_SHADER_PATCHES_ARB 0x82F1
+#define LOCAL_GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define LOCAL_GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define LOCAL_GL_TESS_CONTROL_TEXTURE 0x829C
+#define LOCAL_GL_TESS_EVALUATION_PROGRAM_NV 0x891F
+#define LOCAL_GL_TESS_EVALUATION_PROGRAM_PARAMETER_BUFFER_NV 0x8C75
+#define LOCAL_GL_TESS_EVALUATION_SHADER 0x8E87
+#define LOCAL_GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define LOCAL_GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010
+#define LOCAL_GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+#define LOCAL_GL_TESS_EVALUATION_SHADER_EXT 0x8E87
+#define LOCAL_GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2
+#define LOCAL_GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB 0x82F2
+#define LOCAL_GL_TESS_EVALUATION_SHADER_OES 0x8E87
+#define LOCAL_GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define LOCAL_GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define LOCAL_GL_TESS_EVALUATION_TEXTURE 0x829D
+#define LOCAL_GL_TESS_GEN_MODE 0x8E76
+#define LOCAL_GL_TESS_GEN_MODE_EXT 0x8E76
+#define LOCAL_GL_TESS_GEN_MODE_OES 0x8E76
+#define LOCAL_GL_TESS_GEN_POINT_MODE 0x8E79
+#define LOCAL_GL_TESS_GEN_POINT_MODE_EXT 0x8E79
+#define LOCAL_GL_TESS_GEN_POINT_MODE_OES 0x8E79
+#define LOCAL_GL_TESS_GEN_SPACING 0x8E77
+#define LOCAL_GL_TESS_GEN_SPACING_EXT 0x8E77
+#define LOCAL_GL_TESS_GEN_SPACING_OES 0x8E77
+#define LOCAL_GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define LOCAL_GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78
+#define LOCAL_GL_TESS_GEN_VERTEX_ORDER_OES 0x8E78
+#define LOCAL_GL_TEXCOORD1_BIT_PGI 0x10000000
+#define LOCAL_GL_TEXCOORD2_BIT_PGI 0x20000000
+#define LOCAL_GL_TEXCOORD3_BIT_PGI 0x40000000
+#define LOCAL_GL_TEXCOORD4_BIT_PGI 0x80000000
+#define LOCAL_GL_TEXTURE 0x1702
+#define LOCAL_GL_TEXTURE0 0x84C0
+#define LOCAL_GL_TEXTURE0_ARB 0x84C0
+#define LOCAL_GL_TEXTURE1 0x84C1
+#define LOCAL_GL_TEXTURE10 0x84CA
+#define LOCAL_GL_TEXTURE10_ARB 0x84CA
+#define LOCAL_GL_TEXTURE11 0x84CB
+#define LOCAL_GL_TEXTURE11_ARB 0x84CB
+#define LOCAL_GL_TEXTURE12 0x84CC
+#define LOCAL_GL_TEXTURE12_ARB 0x84CC
+#define LOCAL_GL_TEXTURE13 0x84CD
+#define LOCAL_GL_TEXTURE13_ARB 0x84CD
+#define LOCAL_GL_TEXTURE14 0x84CE
+#define LOCAL_GL_TEXTURE14_ARB 0x84CE
+#define LOCAL_GL_TEXTURE15 0x84CF
+#define LOCAL_GL_TEXTURE15_ARB 0x84CF
+#define LOCAL_GL_TEXTURE16 0x84D0
+#define LOCAL_GL_TEXTURE16_ARB 0x84D0
+#define LOCAL_GL_TEXTURE17 0x84D1
+#define LOCAL_GL_TEXTURE17_ARB 0x84D1
+#define LOCAL_GL_TEXTURE18 0x84D2
+#define LOCAL_GL_TEXTURE18_ARB 0x84D2
+#define LOCAL_GL_TEXTURE19 0x84D3
+#define LOCAL_GL_TEXTURE19_ARB 0x84D3
+#define LOCAL_GL_TEXTURE1_ARB 0x84C1
+#define LOCAL_GL_TEXTURE2 0x84C2
+#define LOCAL_GL_TEXTURE20 0x84D4
+#define LOCAL_GL_TEXTURE20_ARB 0x84D4
+#define LOCAL_GL_TEXTURE21 0x84D5
+#define LOCAL_GL_TEXTURE21_ARB 0x84D5
+#define LOCAL_GL_TEXTURE22 0x84D6
+#define LOCAL_GL_TEXTURE22_ARB 0x84D6
+#define LOCAL_GL_TEXTURE23 0x84D7
+#define LOCAL_GL_TEXTURE23_ARB 0x84D7
+#define LOCAL_GL_TEXTURE24 0x84D8
+#define LOCAL_GL_TEXTURE24_ARB 0x84D8
+#define LOCAL_GL_TEXTURE25 0x84D9
+#define LOCAL_GL_TEXTURE25_ARB 0x84D9
+#define LOCAL_GL_TEXTURE26 0x84DA
+#define LOCAL_GL_TEXTURE26_ARB 0x84DA
+#define LOCAL_GL_TEXTURE27 0x84DB
+#define LOCAL_GL_TEXTURE27_ARB 0x84DB
+#define LOCAL_GL_TEXTURE28 0x84DC
+#define LOCAL_GL_TEXTURE28_ARB 0x84DC
+#define LOCAL_GL_TEXTURE29 0x84DD
+#define LOCAL_GL_TEXTURE29_ARB 0x84DD
+#define LOCAL_GL_TEXTURE2_ARB 0x84C2
+#define LOCAL_GL_TEXTURE3 0x84C3
+#define LOCAL_GL_TEXTURE30 0x84DE
+#define LOCAL_GL_TEXTURE30_ARB 0x84DE
+#define LOCAL_GL_TEXTURE31 0x84DF
+#define LOCAL_GL_TEXTURE31_ARB 0x84DF
+#define LOCAL_GL_TEXTURE3_ARB 0x84C3
+#define LOCAL_GL_TEXTURE4 0x84C4
+#define LOCAL_GL_TEXTURE4_ARB 0x84C4
+#define LOCAL_GL_TEXTURE5 0x84C5
+#define LOCAL_GL_TEXTURE5_ARB 0x84C5
+#define LOCAL_GL_TEXTURE6 0x84C6
+#define LOCAL_GL_TEXTURE6_ARB 0x84C6
+#define LOCAL_GL_TEXTURE7 0x84C7
+#define LOCAL_GL_TEXTURE7_ARB 0x84C7
+#define LOCAL_GL_TEXTURE8 0x84C8
+#define LOCAL_GL_TEXTURE8_ARB 0x84C8
+#define LOCAL_GL_TEXTURE9 0x84C9
+#define LOCAL_GL_TEXTURE9_ARB 0x84C9
+#define LOCAL_GL_TEXTURE_1D 0x0DE0
+#define LOCAL_GL_TEXTURE_1D_ARRAY 0x8C18
+#define LOCAL_GL_TEXTURE_1D_ARRAY_EXT 0x8C18
+#define LOCAL_GL_TEXTURE_1D_BINDING_EXT 0x8068
+#define LOCAL_GL_TEXTURE_1D_STACK_BINDING_MESAX 0x875D
+#define LOCAL_GL_TEXTURE_1D_STACK_MESAX 0x8759
+#define LOCAL_GL_TEXTURE_2D 0x0DE1
+#define LOCAL_GL_TEXTURE_2D_ARRAY 0x8C1A
+#define LOCAL_GL_TEXTURE_2D_ARRAY_EXT 0x8C1A
+#define LOCAL_GL_TEXTURE_2D_BINDING_EXT 0x8069
+#define LOCAL_GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define LOCAL_GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define LOCAL_GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102
+#define LOCAL_GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E
+#define LOCAL_GL_TEXTURE_2D_STACK_MESAX 0x875A
+#define LOCAL_GL_TEXTURE_3D 0x806F
+#define LOCAL_GL_TEXTURE_3D_BINDING_EXT 0x806A
+#define LOCAL_GL_TEXTURE_3D_BINDING_OES 0x806A
+#define LOCAL_GL_TEXTURE_3D_EXT 0x806F
+#define LOCAL_GL_TEXTURE_3D_OES 0x806F
+#define LOCAL_GL_TEXTURE_4DSIZE_SGIS 0x8136
+#define LOCAL_GL_TEXTURE_4D_BINDING_SGIS 0x814F
+#define LOCAL_GL_TEXTURE_4D_SGIS 0x8134
+#define LOCAL_GL_TEXTURE_ALPHA_MODULATE_IMG 0x8C06
+#define LOCAL_GL_TEXTURE_ALPHA_SIZE 0x805F
+#define LOCAL_GL_TEXTURE_ALPHA_SIZE_EXT 0x805F
+#define LOCAL_GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define LOCAL_GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13
+#define LOCAL_GL_TEXTURE_APPLICATION_MODE_EXT 0x834F
+#define LOCAL_GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69
+#define LOCAL_GL_TEXTURE_BASE_LEVEL 0x813C
+#define LOCAL_GL_TEXTURE_BASE_LEVEL_SGIS 0x813C
+#define LOCAL_GL_TEXTURE_BINDING_1D 0x8068
+#define LOCAL_GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define LOCAL_GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C
+#define LOCAL_GL_TEXTURE_BINDING_2D 0x8069
+#define LOCAL_GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define LOCAL_GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D
+#define LOCAL_GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define LOCAL_GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define LOCAL_GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105
+#define LOCAL_GL_TEXTURE_BINDING_3D 0x806A
+#define LOCAL_GL_TEXTURE_BINDING_3D_OES 0x806A
+#define LOCAL_GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define LOCAL_GL_TEXTURE_BINDING_BUFFER_ARB 0x8C2C
+#define LOCAL_GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
+#define LOCAL_GL_TEXTURE_BINDING_BUFFER_OES 0x8C2C
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB 0x900A
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_EXT 0x8514
+#define LOCAL_GL_TEXTURE_BINDING_CUBE_MAP_OES 0x8514
+#define LOCAL_GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67
+#define LOCAL_GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
+#define LOCAL_GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
+#define LOCAL_GL_TEXTURE_BINDING_RENDERBUFFER_NV 0x8E53
+#define LOCAL_GL_TEXTURE_BIT 0x00040000
+#define LOCAL_GL_TEXTURE_BLUE_SIZE 0x805E
+#define LOCAL_GL_TEXTURE_BLUE_SIZE_EXT 0x805E
+#define LOCAL_GL_TEXTURE_BLUE_TYPE 0x8C12
+#define LOCAL_GL_TEXTURE_BLUE_TYPE_ARB 0x8C12
+#define LOCAL_GL_TEXTURE_BORDER 0x1005
+#define LOCAL_GL_TEXTURE_BORDER_COLOR 0x1004
+#define LOCAL_GL_TEXTURE_BORDER_COLOR_EXT 0x1004
+#define LOCAL_GL_TEXTURE_BORDER_COLOR_NV 0x1004
+#define LOCAL_GL_TEXTURE_BORDER_COLOR_OES 0x1004
+#define LOCAL_GL_TEXTURE_BORDER_VALUES_NV 0x871A
+#define LOCAL_GL_TEXTURE_BUFFER 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_ARB 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_BINDING_OES 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define LOCAL_GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB 0x8C2D
+#define LOCAL_GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
+#define LOCAL_GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define LOCAL_GL_TEXTURE_BUFFER_EXT 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E
+#define LOCAL_GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
+#define LOCAL_GL_TEXTURE_BUFFER_OES 0x8C2A
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D
+#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_OES 0x919D
+#define LOCAL_GL_TEXTURE_BUFFER_SIZE 0x919E
+#define LOCAL_GL_TEXTURE_BUFFER_SIZE_EXT 0x919E
+#define LOCAL_GL_TEXTURE_BUFFER_SIZE_OES 0x919E
+#define LOCAL_GL_TEXTURE_CLIPMAP_CENTER_SGIX 0x8171
+#define LOCAL_GL_TEXTURE_CLIPMAP_DEPTH_SGIX 0x8176
+#define LOCAL_GL_TEXTURE_CLIPMAP_FRAME_SGIX 0x8172
+#define LOCAL_GL_TEXTURE_CLIPMAP_LOD_OFFSET_SGIX 0x8175
+#define LOCAL_GL_TEXTURE_CLIPMAP_OFFSET_SGIX 0x8173
+#define LOCAL_GL_TEXTURE_CLIPMAP_VIRTUAL_DEPTH_SGIX 0x8174
+#define LOCAL_GL_TEXTURE_COLOR_SAMPLES_NV 0x9046
+#define LOCAL_GL_TEXTURE_COLOR_TABLE_SGI 0x80BC
+#define LOCAL_GL_TEXTURE_COLOR_WRITEMASK_SGIS 0x81EF
+#define LOCAL_GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF
+#define LOCAL_GL_TEXTURE_COMPARE_FUNC 0x884D
+#define LOCAL_GL_TEXTURE_COMPARE_FUNC_ARB 0x884D
+#define LOCAL_GL_TEXTURE_COMPARE_FUNC_EXT 0x884D
+#define LOCAL_GL_TEXTURE_COMPARE_MODE 0x884C
+#define LOCAL_GL_TEXTURE_COMPARE_MODE_ARB 0x884C
+#define LOCAL_GL_TEXTURE_COMPARE_MODE_EXT 0x884C
+#define LOCAL_GL_TEXTURE_COMPARE_OPERATOR_SGIX 0x819B
+#define LOCAL_GL_TEXTURE_COMPARE_SGIX 0x819A
+#define LOCAL_GL_TEXTURE_COMPONENTS 0x1003
+#define LOCAL_GL_TEXTURE_COMPRESSED 0x86A1
+#define LOCAL_GL_TEXTURE_COMPRESSED_ARB 0x86A1
+#define LOCAL_GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define LOCAL_GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define LOCAL_GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define LOCAL_GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define LOCAL_GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
+#define LOCAL_GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define LOCAL_GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
+#define LOCAL_GL_TEXTURE_CONSTANT_DATA_SUNX 0x81D6
+#define LOCAL_GL_TEXTURE_COORD_ARRAY 0x8078
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_ADDRESS_NV 0x8F25
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_COUNT_EXT 0x808B
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_EXT 0x8078
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_LENGTH_NV 0x8F2F
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_LIST_IBM 103074
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_LIST_STRIDE_IBM 103084
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_PARALLEL_POINTERS_INTEL 0x83F8
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_POINTER_EXT 0x8092
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_SIZE_EXT 0x8088
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_STRIDE_EXT 0x808A
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define LOCAL_GL_TEXTURE_COORD_ARRAY_TYPE_EXT 0x8089
+#define LOCAL_GL_TEXTURE_COORD_NV 0x8C79
+#define LOCAL_GL_TEXTURE_COVERAGE_SAMPLES_NV 0x9045
+#define LOCAL_GL_TEXTURE_CROP_RECT_OES 0x8B9D
+#define LOCAL_GL_TEXTURE_CUBE_MAP 0x8513
+#define LOCAL_GL_TEXTURE_CUBE_MAP_ARB 0x8513
+#define LOCAL_GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define LOCAL_GL_TEXTURE_CUBE_MAP_ARRAY_ARB 0x9009
+#define LOCAL_GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009
+#define LOCAL_GL_TEXTURE_CUBE_MAP_ARRAY_OES 0x9009
+#define LOCAL_GL_TEXTURE_CUBE_MAP_EXT 0x8513
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_EXT 0x8516
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES 0x8516
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT 0x8518
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES 0x8518
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT 0x851A
+#define LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES 0x851A
+#define LOCAL_GL_TEXTURE_CUBE_MAP_OES 0x8513
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT 0x8515
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES 0x8515
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_EXT 0x8517
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES 0x8517
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_EXT 0x8519
+#define LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES 0x8519
+#define LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define LOCAL_GL_TEXTURE_DEFORMATION_BIT_SGIX 0x00000001
+#define LOCAL_GL_TEXTURE_DEFORMATION_SGIX 0x8195
+#define LOCAL_GL_TEXTURE_DEPTH 0x8071
+#define LOCAL_GL_TEXTURE_DEPTH_EXT 0x8071
+#define LOCAL_GL_TEXTURE_DEPTH_QCOM 0x8BD4
+#define LOCAL_GL_TEXTURE_DEPTH_SIZE 0x884A
+#define LOCAL_GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
+#define LOCAL_GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define LOCAL_GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16
+#define LOCAL_GL_TEXTURE_DS_SIZE_NV 0x871D
+#define LOCAL_GL_TEXTURE_DT_SIZE_NV 0x871E
+#define LOCAL_GL_TEXTURE_ENV 0x2300
+#define LOCAL_GL_TEXTURE_ENV_BIAS_SGIX 0x80BE
+#define LOCAL_GL_TEXTURE_ENV_COLOR 0x2201
+#define LOCAL_GL_TEXTURE_ENV_MODE 0x2200
+#define LOCAL_GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define LOCAL_GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define LOCAL_GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008
+#define LOCAL_GL_TEXTURE_FILTER4_SIZE_SGIS 0x8147
+#define LOCAL_GL_TEXTURE_FILTER_CONTROL 0x8500
+#define LOCAL_GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
+#define LOCAL_GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define LOCAL_GL_TEXTURE_FLOAT_COMPONENTS_NV 0x888C
+#define LOCAL_GL_TEXTURE_FORMAT_QCOM 0x8BD6
+#define LOCAL_GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT 0x8FBF
+#define LOCAL_GL_TEXTURE_FOVEATED_CUTOFF_DENSITY_QCOM 0x96A0
+#define LOCAL_GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM 0x8BFB
+#define LOCAL_GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM 0x8BFD
+#define LOCAL_GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM 0x8BFC
+#define LOCAL_GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM 0x8BFE
+#define LOCAL_GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
+#define LOCAL_GL_TEXTURE_GATHER 0x82A2
+#define LOCAL_GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define LOCAL_GL_TEXTURE_GEN_MODE 0x2500
+#define LOCAL_GL_TEXTURE_GEN_MODE_OES 0x2500
+#define LOCAL_GL_TEXTURE_GEN_Q 0x0C63
+#define LOCAL_GL_TEXTURE_GEN_R 0x0C62
+#define LOCAL_GL_TEXTURE_GEN_S 0x0C60
+#define LOCAL_GL_TEXTURE_GEN_STR_OES 0x8D60
+#define LOCAL_GL_TEXTURE_GEN_T 0x0C61
+#define LOCAL_GL_TEXTURE_GEQUAL_R_SGIX 0x819D
+#define LOCAL_GL_TEXTURE_GREEN_SIZE 0x805D
+#define LOCAL_GL_TEXTURE_GREEN_SIZE_EXT 0x805D
+#define LOCAL_GL_TEXTURE_GREEN_TYPE 0x8C11
+#define LOCAL_GL_TEXTURE_GREEN_TYPE_ARB 0x8C11
+#define LOCAL_GL_TEXTURE_HEIGHT 0x1001
+#define LOCAL_GL_TEXTURE_HEIGHT_QCOM 0x8BD3
+#define LOCAL_GL_TEXTURE_HI_SIZE_NV 0x871B
+#define LOCAL_GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define LOCAL_GL_TEXTURE_IMAGE_TYPE 0x8290
+#define LOCAL_GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8
+#define LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define LOCAL_GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F
+#define LOCAL_GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define LOCAL_GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
+#define LOCAL_GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define LOCAL_GL_TEXTURE_INTENSITY_SIZE_EXT 0x8061
+#define LOCAL_GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define LOCAL_GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15
+#define LOCAL_GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define LOCAL_GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5
+#define LOCAL_GL_TEXTURE_LEQUAL_R_SGIX 0x819C
+#define LOCAL_GL_TEXTURE_LIGHTING_MODE_HP 0x8167
+#define LOCAL_GL_TEXTURE_LIGHT_EXT 0x8350
+#define LOCAL_GL_TEXTURE_LOD_BIAS 0x8501
+#define LOCAL_GL_TEXTURE_LOD_BIAS_EXT 0x8501
+#define LOCAL_GL_TEXTURE_LOD_BIAS_R_SGIX 0x8190
+#define LOCAL_GL_TEXTURE_LOD_BIAS_S_SGIX 0x818E
+#define LOCAL_GL_TEXTURE_LOD_BIAS_T_SGIX 0x818F
+#define LOCAL_GL_TEXTURE_LO_SIZE_NV 0x871C
+#define LOCAL_GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define LOCAL_GL_TEXTURE_LUMINANCE_SIZE_EXT 0x8060
+#define LOCAL_GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define LOCAL_GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14
+#define LOCAL_GL_TEXTURE_MAG_FILTER 0x2800
+#define LOCAL_GL_TEXTURE_MAG_SIZE_NV 0x871F
+#define LOCAL_GL_TEXTURE_MATERIAL_FACE_EXT 0x8351
+#define LOCAL_GL_TEXTURE_MATERIAL_PARAMETER_EXT 0x8352
+#define LOCAL_GL_TEXTURE_MATRIX 0x0BA8
+#define LOCAL_GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898F
+#define LOCAL_GL_TEXTURE_MAX_ANISOTROPY 0x84FE
+#define LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+#define LOCAL_GL_TEXTURE_MAX_CLAMP_R_SGIX 0x836B
+#define LOCAL_GL_TEXTURE_MAX_CLAMP_S_SGIX 0x8369
+#define LOCAL_GL_TEXTURE_MAX_CLAMP_T_SGIX 0x836A
+#define LOCAL_GL_TEXTURE_MAX_LEVEL 0x813D
+#define LOCAL_GL_TEXTURE_MAX_LEVEL_APPLE 0x813D
+#define LOCAL_GL_TEXTURE_MAX_LEVEL_SGIS 0x813D
+#define LOCAL_GL_TEXTURE_MAX_LOD 0x813B
+#define LOCAL_GL_TEXTURE_MAX_LOD_SGIS 0x813B
+#define LOCAL_GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF
+#define LOCAL_GL_TEXTURE_MIN_FILTER 0x2801
+#define LOCAL_GL_TEXTURE_MIN_LOD 0x813A
+#define LOCAL_GL_TEXTURE_MIN_LOD_SGIS 0x813A
+#define LOCAL_GL_TEXTURE_MULTI_BUFFER_HINT_SGIX 0x812E
+#define LOCAL_GL_TEXTURE_NORMAL_EXT 0x85AF
+#define LOCAL_GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9
+#define LOCAL_GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB
+#define LOCAL_GL_TEXTURE_POST_SPECULAR_HP 0x8168
+#define LOCAL_GL_TEXTURE_PRE_SPECULAR_HP 0x8169
+#define LOCAL_GL_TEXTURE_PRIORITY 0x8066
+#define LOCAL_GL_TEXTURE_PRIORITY_EXT 0x8066
+#define LOCAL_GL_TEXTURE_PROTECTED_EXT 0x8BFA
+#define LOCAL_GL_TEXTURE_RANGE_LENGTH_APPLE 0x85B7
+#define LOCAL_GL_TEXTURE_RANGE_POINTER_APPLE 0x85B8
+#define LOCAL_GL_TEXTURE_RECTANGLE 0x84F5
+#define LOCAL_GL_TEXTURE_RECTANGLE_ARB 0x84F5
+#define LOCAL_GL_TEXTURE_RECTANGLE_NV 0x84F5
+#define LOCAL_GL_TEXTURE_REDUCTION_MODE_ARB 0x9366
+#define LOCAL_GL_TEXTURE_REDUCTION_MODE_EXT 0x9366
+#define LOCAL_GL_TEXTURE_RED_SIZE 0x805C
+#define LOCAL_GL_TEXTURE_RED_SIZE_EXT 0x805C
+#define LOCAL_GL_TEXTURE_RED_TYPE 0x8C10
+#define LOCAL_GL_TEXTURE_RED_TYPE_ARB 0x8C10
+#define LOCAL_GL_TEXTURE_RENDERBUFFER_DATA_STORE_BINDING_NV 0x8E54
+#define LOCAL_GL_TEXTURE_RENDERBUFFER_NV 0x8E55
+#define LOCAL_GL_TEXTURE_RESIDENT 0x8067
+#define LOCAL_GL_TEXTURE_RESIDENT_EXT 0x8067
+#define LOCAL_GL_TEXTURE_SAMPLES 0x9106
+#define LOCAL_GL_TEXTURE_SAMPLES_IMG 0x9136
+#define LOCAL_GL_TEXTURE_SHADER_NV 0x86DE
+#define LOCAL_GL_TEXTURE_SHADOW 0x82A1
+#define LOCAL_GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define LOCAL_GL_TEXTURE_SHARED_SIZE_EXT 0x8C3F
+#define LOCAL_GL_TEXTURE_SPARSE_ARB 0x91A6
+#define LOCAL_GL_TEXTURE_SPARSE_EXT 0x91A6
+#define LOCAL_GL_TEXTURE_SRGB_DECODE_EXT 0x8A48
+#define LOCAL_GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define LOCAL_GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define LOCAL_GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
+#define LOCAL_GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
+#define LOCAL_GL_TEXTURE_STORAGE_SPARSE_BIT_AMD 0x00000001
+#define LOCAL_GL_TEXTURE_SWIZZLE_A 0x8E45
+#define LOCAL_GL_TEXTURE_SWIZZLE_A_EXT 0x8E45
+#define LOCAL_GL_TEXTURE_SWIZZLE_B 0x8E44
+#define LOCAL_GL_TEXTURE_SWIZZLE_B_EXT 0x8E44
+#define LOCAL_GL_TEXTURE_SWIZZLE_G 0x8E43
+#define LOCAL_GL_TEXTURE_SWIZZLE_G_EXT 0x8E43
+#define LOCAL_GL_TEXTURE_SWIZZLE_R 0x8E42
+#define LOCAL_GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define LOCAL_GL_TEXTURE_SWIZZLE_RGBA_EXT 0x8E46
+#define LOCAL_GL_TEXTURE_SWIZZLE_R_EXT 0x8E42
+#define LOCAL_GL_TEXTURE_TARGET 0x1006
+#define LOCAL_GL_TEXTURE_TARGET_QCOM 0x8BDA
+#define LOCAL_GL_TEXTURE_TILING_EXT 0x9580
+#define LOCAL_GL_TEXTURE_TOO_LARGE_EXT 0x8065
+#define LOCAL_GL_TEXTURE_TYPE_QCOM 0x8BD7
+#define LOCAL_GL_TEXTURE_UNNORMALIZED_COORDINATES_ARM 0x8F6A
+#define LOCAL_GL_TEXTURE_UNSIGNED_REMAP_MODE_NV 0x888F
+#define LOCAL_GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define LOCAL_GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100
+#define LOCAL_GL_TEXTURE_USAGE_ANGLE 0x93A2
+#define LOCAL_GL_TEXTURE_VIEW 0x82B5
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LAYER_OES 0x82DD
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB
+#define LOCAL_GL_TEXTURE_VIEW_MIN_LEVEL_OES 0x82DB
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LAYERS_OES 0x82DE
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC
+#define LOCAL_GL_TEXTURE_VIEW_NUM_LEVELS_OES 0x82DC
+#define LOCAL_GL_TEXTURE_WIDTH 0x1000
+#define LOCAL_GL_TEXTURE_WIDTH_QCOM 0x8BD2
+#define LOCAL_GL_TEXTURE_WRAP_Q_SGIS 0x8137
+#define LOCAL_GL_TEXTURE_WRAP_R 0x8072
+#define LOCAL_GL_TEXTURE_WRAP_R_EXT 0x8072
+#define LOCAL_GL_TEXTURE_WRAP_R_OES 0x8072
+#define LOCAL_GL_TEXTURE_WRAP_S 0x2802
+#define LOCAL_GL_TEXTURE_WRAP_T 0x2803
+#define LOCAL_GL_TEXT_FRAGMENT_SHADER_ATI 0x8200
+#define LOCAL_GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8
+#define LOCAL_GL_TILE_RASTER_ORDER_INCREASING_X_MESA 0x8BB9
+#define LOCAL_GL_TILE_RASTER_ORDER_INCREASING_Y_MESA 0x8BBA
+#define LOCAL_GL_TILING_TYPES_EXT 0x9583
+#define LOCAL_GL_TIMELINE_SEMAPHORE_VALUE_NV 0x9595
+#define LOCAL_GL_TIMEOUT_EXPIRED 0x911B
+#define LOCAL_GL_TIMEOUT_EXPIRED_APPLE 0x911B
+#define LOCAL_GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define LOCAL_GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFF
+#define LOCAL_GL_TIMESTAMP 0x8E28
+#define LOCAL_GL_TIMESTAMP_EXT 0x8E28
+#define LOCAL_GL_TIME_ELAPSED 0x88BF
+#define LOCAL_GL_TIME_ELAPSED_EXT 0x88BF
+#define LOCAL_GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define LOCAL_GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define LOCAL_GL_TRACE_ALL_BITS_MESA 0xFFFF
+#define LOCAL_GL_TRACE_ARRAYS_BIT_MESA 0x0004
+#define LOCAL_GL_TRACE_ERRORS_BIT_MESA 0x0020
+#define LOCAL_GL_TRACE_MASK_MESA 0x8755
+#define LOCAL_GL_TRACE_NAME_MESA 0x8756
+#define LOCAL_GL_TRACE_OPERATIONS_BIT_MESA 0x0001
+#define LOCAL_GL_TRACE_PIXELS_BIT_MESA 0x0010
+#define LOCAL_GL_TRACE_PRIMITIVES_BIT_MESA 0x0002
+#define LOCAL_GL_TRACE_TEXTURES_BIT_MESA 0x0008
+#define LOCAL_GL_TRACK_MATRIX_NV 0x8648
+#define LOCAL_GL_TRACK_MATRIX_TRANSFORM_NV 0x8649
+#define LOCAL_GL_TRANSFORM_BIT 0x00001000
+#define LOCAL_GL_TRANSFORM_FEEDBACK 0x8E22
+#define LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define LOCAL_GL_TRANSFORM_FEEDBACK_ATTRIBS_NV 0x8C7E
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BINDING_NV 0x8E25
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE_NV 0x8E24
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV 0x8C8F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_MODE_NV 0x8C7F
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_NV 0x8C8E
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED_NV 0x8E23
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_NV 0x8C85
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_START_NV 0x8C84
+#define LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+#define LOCAL_GL_TRANSFORM_FEEDBACK_NV 0x8E22
+#define LOCAL_GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC
+#define LOCAL_GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB 0x82EC
+#define LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88
+#define LOCAL_GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV 0x8C88
+#define LOCAL_GL_TRANSFORM_FEEDBACK_RECORD_NV 0x8C86
+#define LOCAL_GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED
+#define LOCAL_GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB 0x82ED
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS_NV 0x8C83
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76
+#define LOCAL_GL_TRANSFORM_HINT_APPLE 0x85B1
+#define LOCAL_GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
+#define LOCAL_GL_TRANSLATE_2D_NV 0x9090
+#define LOCAL_GL_TRANSLATE_3D_NV 0x9091
+#define LOCAL_GL_TRANSLATE_X_NV 0x908E
+#define LOCAL_GL_TRANSLATE_Y_NV 0x908F
+#define LOCAL_GL_TRANSPOSE_AFFINE_2D_NV 0x9096
+#define LOCAL_GL_TRANSPOSE_AFFINE_3D_NV 0x9098
+#define LOCAL_GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define LOCAL_GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
+#define LOCAL_GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
+#define LOCAL_GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define LOCAL_GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
+#define LOCAL_GL_TRANSPOSE_NV 0x862C
+#define LOCAL_GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
+#define LOCAL_GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define LOCAL_GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
+#define LOCAL_GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define LOCAL_GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
+#define LOCAL_GL_TRIANGLES 0x0004
+#define LOCAL_GL_TRIANGLES_ADJACENCY 0x000C
+#define LOCAL_GL_TRIANGLES_ADJACENCY_ARB 0x000C
+#define LOCAL_GL_TRIANGLES_ADJACENCY_EXT 0x000C
+#define LOCAL_GL_TRIANGLES_ADJACENCY_OES 0x000C
+#define LOCAL_GL_TRIANGLE_FAN 0x0006
+#define LOCAL_GL_TRIANGLE_LIST_SUN 0x81D7
+#define LOCAL_GL_TRIANGLE_MESH_SUN 0x8615
+#define LOCAL_GL_TRIANGLE_STRIP 0x0005
+#define LOCAL_GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define LOCAL_GL_TRIANGLE_STRIP_ADJACENCY_ARB 0x000D
+#define LOCAL_GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D
+#define LOCAL_GL_TRIANGLE_STRIP_ADJACENCY_OES 0x000D
+#define LOCAL_GL_TRIANGULAR_NV 0x90A5
+#define LOCAL_GL_TRUE 1
+#define LOCAL_GL_TYPE 0x92FA
+#define LOCAL_GL_UNCORRELATED_NV 0x9282
+#define LOCAL_GL_UNDEFINED_APPLE 0x8A1C
+#define LOCAL_GL_UNDEFINED_VERTEX 0x8260
+#define LOCAL_GL_UNDEFINED_VERTEX_EXT 0x8260
+#define LOCAL_GL_UNDEFINED_VERTEX_OES 0x8260
+#define LOCAL_GL_UNIFORM 0x92E1
+#define LOCAL_GL_UNIFORM_ADDRESS_COMMAND_NV 0x000A
+#define LOCAL_GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define LOCAL_GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define LOCAL_GL_UNIFORM_BARRIER_BIT 0x00000004
+#define LOCAL_GL_UNIFORM_BARRIER_BIT_EXT 0x00000004
+#define LOCAL_GL_UNIFORM_BLOCK 0x92E2
+#define LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define LOCAL_GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define LOCAL_GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define LOCAL_GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV 0x959C
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV 0x959D
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define LOCAL_GL_UNIFORM_BUFFER 0x8A11
+#define LOCAL_GL_UNIFORM_BUFFER_ADDRESS_NV 0x936F
+#define LOCAL_GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define LOCAL_GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF
+#define LOCAL_GL_UNIFORM_BUFFER_EXT 0x8DEE
+#define LOCAL_GL_UNIFORM_BUFFER_LENGTH_NV 0x9370
+#define LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define LOCAL_GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define LOCAL_GL_UNIFORM_BUFFER_START 0x8A29
+#define LOCAL_GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E
+#define LOCAL_GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define LOCAL_GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define LOCAL_GL_UNIFORM_NAME_LENGTH 0x8A39
+#define LOCAL_GL_UNIFORM_OFFSET 0x8A3B
+#define LOCAL_GL_UNIFORM_SIZE 0x8A38
+#define LOCAL_GL_UNIFORM_TYPE 0x8A37
+#define LOCAL_GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255
+#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255
+#define LOCAL_GL_UNPACK_ALIGNMENT 0x0CF5
+#define LOCAL_GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
+#define LOCAL_GL_UNPACK_CMYK_HINT_EXT 0x800F
+#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
+#define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define LOCAL_GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define LOCAL_GL_UNPACK_COMPRESSED_SIZE_SGIX 0x831A
+#define LOCAL_GL_UNPACK_CONSTANT_DATA_SUNX 0x81D5
+#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL 0x9240
+#define LOCAL_GL_UNPACK_IMAGE_DEPTH_SGIS 0x8133
+#define LOCAL_GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define LOCAL_GL_UNPACK_IMAGE_HEIGHT_EXT 0x806E
+#define LOCAL_GL_UNPACK_LSB_FIRST 0x0CF1
+#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
+#define LOCAL_GL_UNPACK_RESAMPLE_OML 0x8985
+#define LOCAL_GL_UNPACK_RESAMPLE_SGIX 0x842F
+#define LOCAL_GL_UNPACK_ROW_BYTES_APPLE 0x8A16
+#define LOCAL_GL_UNPACK_ROW_LENGTH 0x0CF2
+#define LOCAL_GL_UNPACK_ROW_LENGTH_EXT 0x0CF2
+#define LOCAL_GL_UNPACK_SKIP_IMAGES 0x806D
+#define LOCAL_GL_UNPACK_SKIP_IMAGES_EXT 0x806D
+#define LOCAL_GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define LOCAL_GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4
+#define LOCAL_GL_UNPACK_SKIP_ROWS 0x0CF3
+#define LOCAL_GL_UNPACK_SKIP_ROWS_EXT 0x0CF3
+#define LOCAL_GL_UNPACK_SKIP_VOLUMES_SGIS 0x8132
+#define LOCAL_GL_UNPACK_SUBSAMPLE_RATE_SGIX 0x85A1
+#define LOCAL_GL_UNPACK_SWAP_BYTES 0x0CF0
+#define LOCAL_GL_UNSIGNALED 0x9118
+#define LOCAL_GL_UNSIGNALED_APPLE 0x9118
+#define LOCAL_GL_UNSIGNED_BYTE 0x1401
+#define LOCAL_GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define LOCAL_GL_UNSIGNED_BYTE_2_3_3_REV_EXT 0x8362
+#define LOCAL_GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define LOCAL_GL_UNSIGNED_BYTE_3_3_2_EXT 0x8032
+#define LOCAL_GL_UNSIGNED_IDENTITY_NV 0x8536
+#define LOCAL_GL_UNSIGNED_INT 0x1405
+#define LOCAL_GL_UNSIGNED_INT16_NV 0x8FF0
+#define LOCAL_GL_UNSIGNED_INT16_VEC2_NV 0x8FF1
+#define LOCAL_GL_UNSIGNED_INT16_VEC3_NV 0x8FF2
+#define LOCAL_GL_UNSIGNED_INT16_VEC4_NV 0x8FF3
+#define LOCAL_GL_UNSIGNED_INT64_AMD 0x8BC2
+#define LOCAL_GL_UNSIGNED_INT64_ARB 0x140F
+#define LOCAL_GL_UNSIGNED_INT64_NV 0x140F
+#define LOCAL_GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
+#define LOCAL_GL_UNSIGNED_INT64_VEC2_NV 0x8FF5
+#define LOCAL_GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
+#define LOCAL_GL_UNSIGNED_INT64_VEC3_NV 0x8FF6
+#define LOCAL_GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7
+#define LOCAL_GL_UNSIGNED_INT64_VEC4_NV 0x8FF7
+#define LOCAL_GL_UNSIGNED_INT8_NV 0x8FEC
+#define LOCAL_GL_UNSIGNED_INT8_VEC2_NV 0x8FED
+#define LOCAL_GL_UNSIGNED_INT8_VEC3_NV 0x8FEE
+#define LOCAL_GL_UNSIGNED_INT8_VEC4_NV 0x8FEF
+#define LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B
+#define LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV_EXT 0x8C3B
+#define LOCAL_GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define LOCAL_GL_UNSIGNED_INT_10_10_10_2_EXT 0x8036
+#define LOCAL_GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6
+#define LOCAL_GL_UNSIGNED_INT_24_8 0x84FA
+#define LOCAL_GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define LOCAL_GL_UNSIGNED_INT_24_8_MESA 0x8751
+#define LOCAL_GL_UNSIGNED_INT_24_8_NV 0x84FA
+#define LOCAL_GL_UNSIGNED_INT_24_8_OES 0x84FA
+#define LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+#define LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E
+#define LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV_EXT 0x8C3E
+#define LOCAL_GL_UNSIGNED_INT_8_24_REV_MESA 0x8752
+#define LOCAL_GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define LOCAL_GL_UNSIGNED_INT_8_8_8_8_EXT 0x8035
+#define LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV_EXT 0x8367
+#define LOCAL_GL_UNSIGNED_INT_8_8_S8_S8_REV_NV 0x86DB
+#define LOCAL_GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_BUFFER_OES 0x9067
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A
+#define LOCAL_GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#define LOCAL_GL_UNSIGNED_INT_S8_S8_8_8_NV 0x86DA
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_BUFFER_AMD 0x9003
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define LOCAL_GL_UNSIGNED_INT_SAMPLER_RENDERBUFFER_NV 0x8E58
+#define LOCAL_GL_UNSIGNED_INT_VEC2 0x8DC6
+#define LOCAL_GL_UNSIGNED_INT_VEC2_EXT 0x8DC6
+#define LOCAL_GL_UNSIGNED_INT_VEC3 0x8DC7
+#define LOCAL_GL_UNSIGNED_INT_VEC3_EXT 0x8DC7
+#define LOCAL_GL_UNSIGNED_INT_VEC4 0x8DC8
+#define LOCAL_GL_UNSIGNED_INT_VEC4_EXT 0x8DC8
+#define LOCAL_GL_UNSIGNED_INVERT_NV 0x8537
+#define LOCAL_GL_UNSIGNED_NORMALIZED 0x8C17
+#define LOCAL_GL_UNSIGNED_NORMALIZED_ARB 0x8C17
+#define LOCAL_GL_UNSIGNED_NORMALIZED_EXT 0x8C17
+#define LOCAL_GL_UNSIGNED_SHORT 0x1403
+#define LOCAL_GL_UNSIGNED_SHORT_15_1_MESA 0x8753
+#define LOCAL_GL_UNSIGNED_SHORT_1_15_REV_MESA 0x8754
+#define LOCAL_GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define LOCAL_GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
+#define LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define LOCAL_GL_UNSIGNED_SHORT_4_4_4_4_EXT 0x8033
+#define LOCAL_GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define LOCAL_GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
+#define LOCAL_GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365
+#define LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define LOCAL_GL_UNSIGNED_SHORT_5_5_5_1_EXT 0x8034
+#define LOCAL_GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define LOCAL_GL_UNSIGNED_SHORT_5_6_5_EXT 0x8363
+#define LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV_EXT 0x8364
+#define LOCAL_GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA
+#define LOCAL_GL_UNSIGNED_SHORT_8_8_MESA 0x85BA
+#define LOCAL_GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB
+#define LOCAL_GL_UNSIGNED_SHORT_8_8_REV_MESA 0x85BB
+#define LOCAL_GL_UPLOAD_GPU_MASK_NVX 0x954A
+#define LOCAL_GL_UPPER_LEFT 0x8CA2
+#define LOCAL_GL_UPPER_LEFT_EXT 0x8CA2
+#define LOCAL_GL_USE_MISSING_GLYPH_NV 0x90AA
+#define LOCAL_GL_UTF16_NV 0x909B
+#define LOCAL_GL_UTF8_NV 0x909A
+#define LOCAL_GL_UUID_SIZE_EXT 16
+#define LOCAL_GL_V2F 0x2A20
+#define LOCAL_GL_V3F 0x2A21
+#define LOCAL_GL_VALIDATE_SHADER_BINARY_QCOM 0x96A3
+#define LOCAL_GL_VALIDATE_STATUS 0x8B83
+#define LOCAL_GL_VARIABLE_A_NV 0x8523
+#define LOCAL_GL_VARIABLE_B_NV 0x8524
+#define LOCAL_GL_VARIABLE_C_NV 0x8525
+#define LOCAL_GL_VARIABLE_D_NV 0x8526
+#define LOCAL_GL_VARIABLE_E_NV 0x8527
+#define LOCAL_GL_VARIABLE_F_NV 0x8528
+#define LOCAL_GL_VARIABLE_G_NV 0x8529
+#define LOCAL_GL_VARIANT_ARRAY_EXT 0x87E8
+#define LOCAL_GL_VARIANT_ARRAY_POINTER_EXT 0x87E9
+#define LOCAL_GL_VARIANT_ARRAY_STRIDE_EXT 0x87E6
+#define LOCAL_GL_VARIANT_ARRAY_TYPE_EXT 0x87E7
+#define LOCAL_GL_VARIANT_DATATYPE_EXT 0x87E5
+#define LOCAL_GL_VARIANT_EXT 0x87C1
+#define LOCAL_GL_VARIANT_VALUE_EXT 0x87E4
+#define LOCAL_GL_VBO_FREE_MEMORY_ATI 0x87FB
+#define LOCAL_GL_VECTOR_EXT 0x87BF
+#define LOCAL_GL_VENDOR 0x1F00
+#define LOCAL_GL_VERSION 0x1F02
+#define LOCAL_GL_VERSION_ES_CL_1_0 1
+#define LOCAL_GL_VERSION_ES_CL_1_1 1
+#define LOCAL_GL_VERSION_ES_CM_1_1 1
+#define LOCAL_GL_VERTEX23_BIT_PGI 0x00000004
+#define LOCAL_GL_VERTEX4_BIT_PGI 0x00000008
+#define LOCAL_GL_VERTEX_ARRAY 0x8074
+#define LOCAL_GL_VERTEX_ARRAY_ADDRESS_NV 0x8F21
+#define LOCAL_GL_VERTEX_ARRAY_BINDING 0x85B5
+#define LOCAL_GL_VERTEX_ARRAY_BINDING_APPLE 0x85B5
+#define LOCAL_GL_VERTEX_ARRAY_BINDING_OES 0x85B5
+#define LOCAL_GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define LOCAL_GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define LOCAL_GL_VERTEX_ARRAY_COUNT_EXT 0x807D
+#define LOCAL_GL_VERTEX_ARRAY_EXT 0x8074
+#define LOCAL_GL_VERTEX_ARRAY_KHR 0x8074
+#define LOCAL_GL_VERTEX_ARRAY_LENGTH_NV 0x8F2B
+#define LOCAL_GL_VERTEX_ARRAY_LIST_IBM 103070
+#define LOCAL_GL_VERTEX_ARRAY_LIST_STRIDE_IBM 103080
+#define LOCAL_GL_VERTEX_ARRAY_OBJECT_AMD 0x9154
+#define LOCAL_GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
+#define LOCAL_GL_VERTEX_ARRAY_PARALLEL_POINTERS_INTEL 0x83F5
+#define LOCAL_GL_VERTEX_ARRAY_POINTER 0x808E
+#define LOCAL_GL_VERTEX_ARRAY_POINTER_EXT 0x808E
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_APPLE 0x851D
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_LENGTH_APPLE 0x851E
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_LENGTH_NV 0x851E
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_NV 0x851D
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_POINTER_APPLE 0x8521
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_POINTER_NV 0x8521
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_VALID_NV 0x851F
+#define LOCAL_GL_VERTEX_ARRAY_RANGE_WITHOUT_FLUSH_NV 0x8533
+#define LOCAL_GL_VERTEX_ARRAY_SIZE 0x807A
+#define LOCAL_GL_VERTEX_ARRAY_SIZE_EXT 0x807A
+#define LOCAL_GL_VERTEX_ARRAY_STORAGE_HINT_APPLE 0x851F
+#define LOCAL_GL_VERTEX_ARRAY_STRIDE 0x807C
+#define LOCAL_GL_VERTEX_ARRAY_STRIDE_EXT 0x807C
+#define LOCAL_GL_VERTEX_ARRAY_TYPE 0x807B
+#define LOCAL_GL_VERTEX_ARRAY_TYPE_EXT 0x807B
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY0_NV 0x8650
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY10_NV 0x865A
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY11_NV 0x865B
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY12_NV 0x865C
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY13_NV 0x865D
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY14_NV 0x865E
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY15_NV 0x865F
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY1_NV 0x8651
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY2_NV 0x8652
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY3_NV 0x8653
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY4_NV 0x8654
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY5_NV 0x8655
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY6_NV 0x8656
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY7_NV 0x8657
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY8_NV 0x8658
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY9_NV 0x8659
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV 0x8F20
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB 0x88FE
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_LENGTH_NV 0x8F2A
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
+#define LOCAL_GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV 0x8F1E
+#define LOCAL_GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define LOCAL_GL_VERTEX_ATTRIB_MAP1_APPLE 0x8A00
+#define LOCAL_GL_VERTEX_ATTRIB_MAP1_COEFF_APPLE 0x8A03
+#define LOCAL_GL_VERTEX_ATTRIB_MAP1_DOMAIN_APPLE 0x8A05
+#define LOCAL_GL_VERTEX_ATTRIB_MAP1_ORDER_APPLE 0x8A04
+#define LOCAL_GL_VERTEX_ATTRIB_MAP1_SIZE_APPLE 0x8A02
+#define LOCAL_GL_VERTEX_ATTRIB_MAP2_APPLE 0x8A01
+#define LOCAL_GL_VERTEX_ATTRIB_MAP2_COEFF_APPLE 0x8A07
+#define LOCAL_GL_VERTEX_ATTRIB_MAP2_DOMAIN_APPLE 0x8A09
+#define LOCAL_GL_VERTEX_ATTRIB_MAP2_ORDER_APPLE 0x8A08
+#define LOCAL_GL_VERTEX_ATTRIB_MAP2_SIZE_APPLE 0x8A06
+#define LOCAL_GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define LOCAL_GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define LOCAL_GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define LOCAL_GL_VERTEX_BINDING_OFFSET 0x82D7
+#define LOCAL_GL_VERTEX_BINDING_STRIDE 0x82D8
+#define LOCAL_GL_VERTEX_BLEND_ARB 0x86A7
+#define LOCAL_GL_VERTEX_CONSISTENT_HINT_PGI 0x1A22B
+#define LOCAL_GL_VERTEX_DATA_HINT_PGI 0x1A22A
+#define LOCAL_GL_VERTEX_ELEMENT_SWIZZLE_AMD 0x91A4
+#define LOCAL_GL_VERTEX_ID_NV 0x8C7B
+#define LOCAL_GL_VERTEX_ID_SWIZZLE_AMD 0x91A5
+#define LOCAL_GL_VERTEX_PRECLIP_HINT_SGIX 0x83EF
+#define LOCAL_GL_VERTEX_PRECLIP_SGIX 0x83EE
+#define LOCAL_GL_VERTEX_PROGRAM_ARB 0x8620
+#define LOCAL_GL_VERTEX_PROGRAM_BINDING_NV 0x864A
+#define LOCAL_GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA 0x8BB7
+#define LOCAL_GL_VERTEX_PROGRAM_CALLBACK_FUNC_MESA 0x8BB6
+#define LOCAL_GL_VERTEX_PROGRAM_CALLBACK_MESA 0x8BB5
+#define LOCAL_GL_VERTEX_PROGRAM_NV 0x8620
+#define LOCAL_GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8DA2
+#define LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
+#define LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
+#define LOCAL_GL_VERTEX_PROGRAM_POSITION_MESA 0x8BB4
+#define LOCAL_GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define LOCAL_GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
+#define LOCAL_GL_VERTEX_PROGRAM_TWO_SIDE_NV 0x8643
+#define LOCAL_GL_VERTEX_SHADER 0x8B31
+#define LOCAL_GL_VERTEX_SHADER_ARB 0x8B31
+#define LOCAL_GL_VERTEX_SHADER_BINDING_EXT 0x8781
+#define LOCAL_GL_VERTEX_SHADER_BIT 0x00000001
+#define LOCAL_GL_VERTEX_SHADER_BIT_EXT 0x00000001
+#define LOCAL_GL_VERTEX_SHADER_EXT 0x8780
+#define LOCAL_GL_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CF
+#define LOCAL_GL_VERTEX_SHADER_INVARIANTS_EXT 0x87D1
+#define LOCAL_GL_VERTEX_SHADER_INVOCATIONS 0x82F0
+#define LOCAL_GL_VERTEX_SHADER_INVOCATIONS_ARB 0x82F0
+#define LOCAL_GL_VERTEX_SHADER_LOCALS_EXT 0x87D3
+#define LOCAL_GL_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87D2
+#define LOCAL_GL_VERTEX_SHADER_OPTIMIZED_EXT 0x87D4
+#define LOCAL_GL_VERTEX_SHADER_VARIANTS_EXT 0x87D0
+#define LOCAL_GL_VERTEX_SOURCE_ATI 0x8774
+#define LOCAL_GL_VERTEX_STATE_PROGRAM_NV 0x8621
+#define LOCAL_GL_VERTEX_STREAM0_ATI 0x876C
+#define LOCAL_GL_VERTEX_STREAM1_ATI 0x876D
+#define LOCAL_GL_VERTEX_STREAM2_ATI 0x876E
+#define LOCAL_GL_VERTEX_STREAM3_ATI 0x876F
+#define LOCAL_GL_VERTEX_STREAM4_ATI 0x8770
+#define LOCAL_GL_VERTEX_STREAM5_ATI 0x8771
+#define LOCAL_GL_VERTEX_STREAM6_ATI 0x8772
+#define LOCAL_GL_VERTEX_STREAM7_ATI 0x8773
+#define LOCAL_GL_VERTEX_SUBROUTINE 0x92E8
+#define LOCAL_GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define LOCAL_GL_VERTEX_TEXTURE 0x829B
+#define LOCAL_GL_VERTEX_WEIGHTING_EXT 0x8509
+#define LOCAL_GL_VERTEX_WEIGHT_ARRAY_EXT 0x850C
+#define LOCAL_GL_VERTEX_WEIGHT_ARRAY_POINTER_EXT 0x8510
+#define LOCAL_GL_VERTEX_WEIGHT_ARRAY_SIZE_EXT 0x850D
+#define LOCAL_GL_VERTEX_WEIGHT_ARRAY_STRIDE_EXT 0x850F
+#define LOCAL_GL_VERTEX_WEIGHT_ARRAY_TYPE_EXT 0x850E
+#define LOCAL_GL_VERTICAL_LINE_TO_NV 0x08
+#define LOCAL_GL_VERTICES_SUBMITTED 0x82EE
+#define LOCAL_GL_VERTICES_SUBMITTED_ARB 0x82EE
+#define LOCAL_GL_VIBRANCE_BIAS_NV 0x8719
+#define LOCAL_GL_VIBRANCE_SCALE_NV 0x8713
+#define LOCAL_GL_VIDEO_BUFFER_BINDING_NV 0x9021
+#define LOCAL_GL_VIDEO_BUFFER_INTERNAL_FORMAT_NV 0x902D
+#define LOCAL_GL_VIDEO_BUFFER_NV 0x9020
+#define LOCAL_GL_VIDEO_BUFFER_PITCH_NV 0x9028
+#define LOCAL_GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV 0x903B
+#define LOCAL_GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV 0x903A
+#define LOCAL_GL_VIDEO_CAPTURE_FRAME_HEIGHT_NV 0x9039
+#define LOCAL_GL_VIDEO_CAPTURE_FRAME_WIDTH_NV 0x9038
+#define LOCAL_GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV 0x903C
+#define LOCAL_GL_VIDEO_CAPTURE_TO_422_SUPPORTED_NV 0x9026
+#define LOCAL_GL_VIDEO_COLOR_CONVERSION_MATRIX_NV 0x9029
+#define LOCAL_GL_VIDEO_COLOR_CONVERSION_MAX_NV 0x902A
+#define LOCAL_GL_VIDEO_COLOR_CONVERSION_MIN_NV 0x902B
+#define LOCAL_GL_VIDEO_COLOR_CONVERSION_OFFSET_NV 0x902C
+#define LOCAL_GL_VIEWPORT 0x0BA2
+#define LOCAL_GL_VIEWPORT_BIT 0x00000800
+#define LOCAL_GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define LOCAL_GL_VIEWPORT_BOUNDS_RANGE_EXT 0x825D
+#define LOCAL_GL_VIEWPORT_BOUNDS_RANGE_NV 0x825D
+#define LOCAL_GL_VIEWPORT_BOUNDS_RANGE_OES 0x825D
+#define LOCAL_GL_VIEWPORT_COMMAND_NV 0x0010
+#define LOCAL_GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define LOCAL_GL_VIEWPORT_INDEX_PROVOKING_VERTEX_EXT 0x825F
+#define LOCAL_GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F
+#define LOCAL_GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES 0x825F
+#define LOCAL_GL_VIEWPORT_POSITION_W_SCALE_NV 0x937C
+#define LOCAL_GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D
+#define LOCAL_GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E
+#define LOCAL_GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+#define LOCAL_GL_VIEWPORT_SUBPIXEL_BITS_EXT 0x825C
+#define LOCAL_GL_VIEWPORT_SUBPIXEL_BITS_NV 0x825C
+#define LOCAL_GL_VIEWPORT_SUBPIXEL_BITS_OES 0x825C
+#define LOCAL_GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357
+#define LOCAL_GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351
+#define LOCAL_GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353
+#define LOCAL_GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355
+#define LOCAL_GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356
+#define LOCAL_GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350
+#define LOCAL_GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352
+#define LOCAL_GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354
+#define LOCAL_GL_VIEWPORT_SWIZZLE_W_NV 0x935B
+#define LOCAL_GL_VIEWPORT_SWIZZLE_X_NV 0x9358
+#define LOCAL_GL_VIEWPORT_SWIZZLE_Y_NV 0x9359
+#define LOCAL_GL_VIEWPORT_SWIZZLE_Z_NV 0x935A
+#define LOCAL_GL_VIEW_CLASS_128_BITS 0x82C4
+#define LOCAL_GL_VIEW_CLASS_16_BITS 0x82CA
+#define LOCAL_GL_VIEW_CLASS_24_BITS 0x82C9
+#define LOCAL_GL_VIEW_CLASS_32_BITS 0x82C8
+#define LOCAL_GL_VIEW_CLASS_48_BITS 0x82C7
+#define LOCAL_GL_VIEW_CLASS_64_BITS 0x82C6
+#define LOCAL_GL_VIEW_CLASS_8_BITS 0x82CB
+#define LOCAL_GL_VIEW_CLASS_96_BITS 0x82C5
+#define LOCAL_GL_VIEW_CLASS_ASTC_10x10_RGBA 0x9393
+#define LOCAL_GL_VIEW_CLASS_ASTC_10x5_RGBA 0x9390
+#define LOCAL_GL_VIEW_CLASS_ASTC_10x6_RGBA 0x9391
+#define LOCAL_GL_VIEW_CLASS_ASTC_10x8_RGBA 0x9392
+#define LOCAL_GL_VIEW_CLASS_ASTC_12x10_RGBA 0x9394
+#define LOCAL_GL_VIEW_CLASS_ASTC_12x12_RGBA 0x9395
+#define LOCAL_GL_VIEW_CLASS_ASTC_4x4_RGBA 0x9388
+#define LOCAL_GL_VIEW_CLASS_ASTC_5x4_RGBA 0x9389
+#define LOCAL_GL_VIEW_CLASS_ASTC_5x5_RGBA 0x938A
+#define LOCAL_GL_VIEW_CLASS_ASTC_6x5_RGBA 0x938B
+#define LOCAL_GL_VIEW_CLASS_ASTC_6x6_RGBA 0x938C
+#define LOCAL_GL_VIEW_CLASS_ASTC_8x5_RGBA 0x938D
+#define LOCAL_GL_VIEW_CLASS_ASTC_8x6_RGBA 0x938E
+#define LOCAL_GL_VIEW_CLASS_ASTC_8x8_RGBA 0x938F
+#define LOCAL_GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define LOCAL_GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define LOCAL_GL_VIEW_CLASS_EAC_R11 0x9383
+#define LOCAL_GL_VIEW_CLASS_EAC_RG11 0x9384
+#define LOCAL_GL_VIEW_CLASS_ETC2_EAC_RGBA 0x9387
+#define LOCAL_GL_VIEW_CLASS_ETC2_RGB 0x9385
+#define LOCAL_GL_VIEW_CLASS_ETC2_RGBA 0x9386
+#define LOCAL_GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define LOCAL_GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define LOCAL_GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define LOCAL_GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define LOCAL_GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define LOCAL_GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define LOCAL_GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_INDEX_ARB 0x91A7
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_INDEX_EXT 0x91A7
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_X_AMD 0x9195
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_X_ARB 0x9195
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_X_EXT 0x9195
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Y_AMD 0x9196
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Y_ARB 0x9196
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Y_EXT 0x9196
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Z_AMD 0x9197
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Z_ARB 0x9197
+#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Z_EXT 0x9197
+#define LOCAL_GL_VIVIDLIGHT_NV 0x92A6
+#define LOCAL_GL_VOLATILE_APPLE 0x8A1A
+#define LOCAL_GL_WAIT_FAILED 0x911D
+#define LOCAL_GL_WAIT_FAILED_APPLE 0x911D
+#define LOCAL_GL_WARPS_PER_SM_NV 0x933A
+#define LOCAL_GL_WARP_SIZE_NV 0x9339
+#define LOCAL_GL_WEIGHTED_AVERAGE_ARB 0x9367
+#define LOCAL_GL_WEIGHTED_AVERAGE_EXT 0x9367
+#define LOCAL_GL_WEIGHT_ARRAY_ARB 0x86AD
+#define LOCAL_GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define LOCAL_GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define LOCAL_GL_WEIGHT_ARRAY_BUFFER_BINDING_OES 0x889E
+#define LOCAL_GL_WEIGHT_ARRAY_OES 0x86AD
+#define LOCAL_GL_WEIGHT_ARRAY_POINTER_ARB 0x86AC
+#define LOCAL_GL_WEIGHT_ARRAY_POINTER_OES 0x86AC
+#define LOCAL_GL_WEIGHT_ARRAY_SIZE_ARB 0x86AB
+#define LOCAL_GL_WEIGHT_ARRAY_SIZE_OES 0x86AB
+#define LOCAL_GL_WEIGHT_ARRAY_STRIDE_ARB 0x86AA
+#define LOCAL_GL_WEIGHT_ARRAY_STRIDE_OES 0x86AA
+#define LOCAL_GL_WEIGHT_ARRAY_TYPE_ARB 0x86A9
+#define LOCAL_GL_WEIGHT_ARRAY_TYPE_OES 0x86A9
+#define LOCAL_GL_WEIGHT_SUM_UNITY_ARB 0x86A6
+#define LOCAL_GL_WIDE_LINE_HINT_PGI 0x1A222
+#define LOCAL_GL_WINDOW_RECTANGLE_EXT 0x8F12
+#define LOCAL_GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13
+#define LOCAL_GL_WRAP_BORDER_SUN 0x81D4
+#define LOCAL_GL_WRITEONLY_RENDERING_QCOM 0x8823
+#define LOCAL_GL_WRITE_DISCARD_NV 0x88BE
+#define LOCAL_GL_WRITE_ONLY 0x88B9
+#define LOCAL_GL_WRITE_ONLY_ARB 0x88B9
+#define LOCAL_GL_WRITE_ONLY_OES 0x88B9
+#define LOCAL_GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV 0x887A
+#define LOCAL_GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
+#define LOCAL_GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV 0x887C
+#define LOCAL_GL_W_EXT 0x87D8
+#define LOCAL_GL_XOR 0x1506
+#define LOCAL_GL_XOR_NV 0x1506
+#define LOCAL_GL_X_EXT 0x87D5
+#define LOCAL_GL_YCBAYCR8A_4224_NV 0x9032
+#define LOCAL_GL_YCBCR_422_APPLE 0x85B9
+#define LOCAL_GL_YCBCR_MESA 0x8757
+#define LOCAL_GL_YCBYCR8_422_NV 0x9031
+#define LOCAL_GL_YCRCBA_SGIX 0x8319
+#define LOCAL_GL_YCRCB_422_SGIX 0x81BB
+#define LOCAL_GL_YCRCB_444_SGIX 0x81BC
+#define LOCAL_GL_YCRCB_SGIX 0x8318
+#define LOCAL_GL_Y_EXT 0x87D6
+#define LOCAL_GL_Z400_BINARY_AMD 0x8740
+#define LOCAL_GL_Z4Y12Z4CB12Z4A12Z4Y12Z4CR12Z4A12_4224_NV 0x9036
+#define LOCAL_GL_Z4Y12Z4CB12Z4CR12_444_NV 0x9037
+#define LOCAL_GL_Z4Y12Z4CB12Z4Y12Z4CR12_422_NV 0x9035
+#define LOCAL_GL_Z6Y10Z6CB10Z6A10Z6Y10Z6CR10Z6A10_4224_NV 0x9034
+#define LOCAL_GL_Z6Y10Z6CB10Z6Y10Z6CR10_422_NV 0x9033
+#define LOCAL_GL_ZERO 0
+#define LOCAL_GL_ZERO_EXT 0x87DD
+#define LOCAL_GL_ZERO_TO_ONE 0x935F
+#define LOCAL_GL_ZERO_TO_ONE_EXT 0x935F
+#define LOCAL_GL_ZOOM_X 0x0D16
+#define LOCAL_GL_ZOOM_Y 0x0D17
+#define LOCAL_GL_Z_EXT 0x87D7
+
+// EGL
+#define LOCAL_EGL_ALPHA_FORMAT 0x3088
+#define LOCAL_EGL_ALPHA_FORMAT_NONPRE 0x308B
+#define LOCAL_EGL_ALPHA_FORMAT_PRE 0x308C
+#define LOCAL_EGL_ALPHA_MASK_SIZE 0x303E
+#define LOCAL_EGL_ALPHA_SIZE 0x3021
+#define LOCAL_EGL_ALREADY_SIGNALED_NV 0x30EA
+#define LOCAL_EGL_AUTO_STEREO_NV 0x3136
+#define LOCAL_EGL_BACK_BUFFER 0x3084
+#define LOCAL_EGL_BAD_ACCESS 0x3002
+#define LOCAL_EGL_BAD_ALLOC 0x3003
+#define LOCAL_EGL_BAD_ATTRIBUTE 0x3004
+#define LOCAL_EGL_BAD_CONFIG 0x3005
+#define LOCAL_EGL_BAD_CONTEXT 0x3006
+#define LOCAL_EGL_BAD_CURRENT_SURFACE 0x3007
+#define LOCAL_EGL_BAD_DEVICE_EXT 0x322B
+#define LOCAL_EGL_BAD_DISPLAY 0x3008
+#define LOCAL_EGL_BAD_MATCH 0x3009
+#define LOCAL_EGL_BAD_NATIVE_PIXMAP 0x300A
+#define LOCAL_EGL_BAD_NATIVE_WINDOW 0x300B
+#define LOCAL_EGL_BAD_OUTPUT_LAYER_EXT 0x322D
+#define LOCAL_EGL_BAD_OUTPUT_PORT_EXT 0x322E
+#define LOCAL_EGL_BAD_PARAMETER 0x300C
+#define LOCAL_EGL_BAD_STATE_KHR 0x321C
+#define LOCAL_EGL_BAD_STREAM_KHR 0x321B
+#define LOCAL_EGL_BAD_SURFACE 0x300D
+#define LOCAL_EGL_BIND_TO_TEXTURE_RGB 0x3039
+#define LOCAL_EGL_BIND_TO_TEXTURE_RGBA 0x303A
+#define LOCAL_EGL_BITMAP_ORIGIN_KHR 0x30C8
+#define LOCAL_EGL_BITMAP_PITCH_KHR 0x30C7
+#define LOCAL_EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC
+#define LOCAL_EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB
+#define LOCAL_EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA
+#define LOCAL_EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD
+#define LOCAL_EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9
+#define LOCAL_EGL_BITMAP_PIXEL_SIZE_KHR 0x3110
+#define LOCAL_EGL_BITMAP_POINTER_KHR 0x30C6
+#define LOCAL_EGL_BLUE_SIZE 0x3022
+#define LOCAL_EGL_BOTTOM_NV 0x336E
+#define LOCAL_EGL_BUFFER_AGE_EXT 0x313D
+#define LOCAL_EGL_BUFFER_AGE_KHR 0x313D
+#define LOCAL_EGL_BUFFER_COUNT_NV 0x321D
+#define LOCAL_EGL_BUFFER_DESTROYED 0x3095
+#define LOCAL_EGL_BUFFER_PRESERVED 0x3094
+#define LOCAL_EGL_BUFFER_SIZE 0x3020
+#define LOCAL_EGL_CLIENT_APIS 0x308D
+#define LOCAL_EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74
+#define LOCAL_EGL_CL_EVENT_HANDLE 0x309C
+#define LOCAL_EGL_CL_EVENT_HANDLE_KHR 0x309C
+#define LOCAL_EGL_COLORSPACE 0x3087
+#define LOCAL_EGL_COLORSPACE_LINEAR 0x308A
+#define LOCAL_EGL_COLORSPACE_sRGB 0x3089
+#define LOCAL_EGL_COLOR_ARGB_HI 0x8F73
+#define LOCAL_EGL_COLOR_BUFFER_TYPE 0x303F
+#define LOCAL_EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
+#define LOCAL_EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
+#define LOCAL_EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT 0x333B
+#define LOCAL_EGL_COLOR_COMPONENT_TYPE_INTEGER_ARM 0x3288
+#define LOCAL_EGL_COLOR_COMPONENT_TYPE_UNSIGNED_INTEGER_ARM 0x3287
+#define LOCAL_EGL_COLOR_FORMAT_HI 0x8F70
+#define LOCAL_EGL_COLOR_RGBA_HI 0x8F72
+#define LOCAL_EGL_COLOR_RGB_HI 0x8F71
+#define LOCAL_EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define LOCAL_EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define LOCAL_EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define LOCAL_EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define LOCAL_EGL_COMPOSITOR_DROP_NEWEST_FRAME_EXT 0x3462
+#define LOCAL_EGL_COMPOSITOR_KEEP_NEWEST_FRAME_EXT 0x3463
+#define LOCAL_EGL_CONDITION_SATISFIED 0x30F6
+#define LOCAL_EGL_CONDITION_SATISFIED_KHR 0x30F6
+#define LOCAL_EGL_CONDITION_SATISFIED_NV 0x30EC
+#define LOCAL_EGL_CONFIG_CAVEAT 0x3027
+#define LOCAL_EGL_CONFIG_ID 0x3028
+#define LOCAL_EGL_CONFIG_SELECT_GROUP_EXT 0x34C0
+#define LOCAL_EGL_CONFORMANT 0x3042
+#define LOCAL_EGL_CONFORMANT_KHR 0x3042
+#define LOCAL_EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E
+#define LOCAL_EGL_CONSUMER_AUTO_ORIENTATION_NV 0x3369
+#define LOCAL_EGL_CONSUMER_FRAME_KHR 0x3213
+#define LOCAL_EGL_CONSUMER_LATENCY_USEC_KHR 0x3210
+#define LOCAL_EGL_CONSUMER_MAX_FRAME_HINT_NV 0x3338
+#define LOCAL_EGL_CONSUMER_METADATA_NV 0x3254
+#define LOCAL_EGL_CONTEXT_CLIENT_TYPE 0x3097
+#define LOCAL_EGL_CONTEXT_CLIENT_VERSION 0x3098
+#define LOCAL_EGL_CONTEXT_FLAGS_KHR 0x30FC
+#define LOCAL_EGL_CONTEXT_LOST 0x300E
+#define LOCAL_EGL_CONTEXT_MAJOR_VERSION 0x3098
+#define LOCAL_EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
+#define LOCAL_EGL_CONTEXT_MINOR_VERSION 0x30FB
+#define LOCAL_EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
+#define LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
+#define LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
+#define LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
+#define LOCAL_EGL_CONTEXT_OPENGL_DEBUG 0x31B0
+#define LOCAL_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
+#define LOCAL_EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
+#define LOCAL_EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
+#define LOCAL_EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3
+#define LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
+#define LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
+#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD
+#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
+#define LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2
+#define LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
+#define LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
+#define LOCAL_EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
+#define LOCAL_EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100
+#define LOCAL_EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
+#define LOCAL_EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
+#define LOCAL_EGL_CONTEXT_PRIORITY_REALTIME_NV 0x3357
+#define LOCAL_EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+#define LOCAL_EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
+#define LOCAL_EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define LOCAL_EGL_CORE_NATIVE_ENGINE 0x305B
+#define LOCAL_EGL_COVERAGE_BUFFERS_NV 0x30E0
+#define LOCAL_EGL_COVERAGE_SAMPLES_NV 0x30E1
+#define LOCAL_EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132
+#define LOCAL_EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133
+#define LOCAL_EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131
+#define LOCAL_EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT 0x3360
+#define LOCAL_EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT 0x3361
+#define LOCAL_EGL_CUDA_DEVICE_NV 0x323A
+#define LOCAL_EGL_CUDA_EVENT_HANDLE_NV 0x323B
+#define LOCAL_EGL_D3D11_DEVICE_ANGLE 0x33A1
+#define LOCAL_EGL_D3D9_DEVICE_ANGLE 0x33A0
+#define LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200
+#define LOCAL_EGL_DEBUG_CALLBACK_KHR 0x33B8
+#define LOCAL_EGL_DEBUG_MSG_CRITICAL_KHR 0x33B9
+#define LOCAL_EGL_DEBUG_MSG_ERROR_KHR 0x33BA
+#define LOCAL_EGL_DEBUG_MSG_INFO_KHR 0x33BC
+#define LOCAL_EGL_DEBUG_MSG_WARN_KHR 0x33BB
+#define LOCAL_EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0)
+#define LOCAL_EGL_DEPTH_ENCODING_NONE_NV 0
+#define LOCAL_EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3
+#define LOCAL_EGL_DEPTH_ENCODING_NV 0x30E2
+#define LOCAL_EGL_DEPTH_SIZE 0x3025
+#define LOCAL_EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define LOCAL_EGL_DEVICE_EXT 0x322C
+#define LOCAL_EGL_DEVICE_UUID_EXT 0x335C
+#define LOCAL_EGL_DISCARD_SAMPLES_ARM 0x3286
+#define LOCAL_EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define LOCAL_EGL_DISPLAY_SCALING 10000
+#define LOCAL_EGL_DMA_BUF_PLANE0_FD_EXT 0x3272
+#define LOCAL_EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444
+#define LOCAL_EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443
+#define LOCAL_EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273
+#define LOCAL_EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274
+#define LOCAL_EGL_DMA_BUF_PLANE1_FD_EXT 0x3275
+#define LOCAL_EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446
+#define LOCAL_EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445
+#define LOCAL_EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276
+#define LOCAL_EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277
+#define LOCAL_EGL_DMA_BUF_PLANE2_FD_EXT 0x3278
+#define LOCAL_EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448
+#define LOCAL_EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447
+#define LOCAL_EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279
+#define LOCAL_EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A
+#define LOCAL_EGL_DMA_BUF_PLANE3_FD_EXT 0x3440
+#define LOCAL_EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A
+#define LOCAL_EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449
+#define LOCAL_EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441
+#define LOCAL_EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442
+#define LOCAL_EGL_DONT_CARE EGL_CAST(EGLint,-1)
+#define LOCAL_EGL_DRAW 0x3059
+#define LOCAL_EGL_DRIVER_NAME_EXT 0x335E
+#define LOCAL_EGL_DRIVER_UUID_EXT 0x335D
+#define LOCAL_EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2
+#define LOCAL_EGL_DRM_BUFFER_FORMAT_MESA 0x31D0
+#define LOCAL_EGL_DRM_BUFFER_MESA 0x31D3
+#define LOCAL_EGL_DRM_BUFFER_STRIDE_MESA 0x31D4
+#define LOCAL_EGL_DRM_BUFFER_USE_CURSOR_MESA 0x00000004
+#define LOCAL_EGL_DRM_BUFFER_USE_MESA 0x31D1
+#define LOCAL_EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001
+#define LOCAL_EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002
+#define LOCAL_EGL_DRM_CONNECTOR_EXT 0x3236
+#define LOCAL_EGL_DRM_CRTC_EXT 0x3234
+#define LOCAL_EGL_DRM_DEVICE_FILE_EXT 0x3233
+#define LOCAL_EGL_DRM_MASTER_FD_EXT 0x333C
+#define LOCAL_EGL_DRM_PLANE_EXT 0x3235
+#define LOCAL_EGL_DRM_RENDER_NODE_FILE_EXT 0x3377
+#define LOCAL_EGL_EXTENSIONS 0x3055
+#define LOCAL_EGL_EXTERNAL_REF_ID_EXT 0x3461
+#define LOCAL_EGL_FALSE 0
+#define LOCAL_EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define LOCAL_EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define LOCAL_EGL_FIXED_SIZE_ANGLE 0x3201
+#define LOCAL_EGL_FOREVER 0xFFFFFFFFFFFFFFFF
+#define LOCAL_EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFF
+#define LOCAL_EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFF
+#define LOCAL_EGL_FORMAT_ASTC_10X10_QCOM 0x33ED
+#define LOCAL_EGL_FORMAT_ASTC_10X10_SRGB_QCOM 0x340B
+#define LOCAL_EGL_FORMAT_ASTC_10X5_QCOM 0x33EA
+#define LOCAL_EGL_FORMAT_ASTC_10X5_SRGB_QCOM 0x3408
+#define LOCAL_EGL_FORMAT_ASTC_10X6_QCOM 0x33EB
+#define LOCAL_EGL_FORMAT_ASTC_10X6_SRGB_QCOM 0x3409
+#define LOCAL_EGL_FORMAT_ASTC_10X8_QCOM 0x33EC
+#define LOCAL_EGL_FORMAT_ASTC_10X8_SRGB_QCOM 0x340A
+#define LOCAL_EGL_FORMAT_ASTC_12X10_QCOM 0x33EE
+#define LOCAL_EGL_FORMAT_ASTC_12X10_SRGB_QCOM 0x340C
+#define LOCAL_EGL_FORMAT_ASTC_12X12_QCOM 0x33EF
+#define LOCAL_EGL_FORMAT_ASTC_12X12_SRGB_QCOM 0x340D
+#define LOCAL_EGL_FORMAT_ASTC_4X4_QCOM 0x33E2
+#define LOCAL_EGL_FORMAT_ASTC_4X4_SRGB_QCOM 0x3400
+#define LOCAL_EGL_FORMAT_ASTC_5X4_QCOM 0x33E3
+#define LOCAL_EGL_FORMAT_ASTC_5X4_SRGB_QCOM 0x3401
+#define LOCAL_EGL_FORMAT_ASTC_5X5_QCOM 0x33E4
+#define LOCAL_EGL_FORMAT_ASTC_5X5_SRGB_QCOM 0x3402
+#define LOCAL_EGL_FORMAT_ASTC_6X5_QCOM 0x33E5
+#define LOCAL_EGL_FORMAT_ASTC_6X5_SRGB_QCOM 0x3403
+#define LOCAL_EGL_FORMAT_ASTC_6X6_QCOM 0x33E6
+#define LOCAL_EGL_FORMAT_ASTC_6X6_SRGB_QCOM 0x3404
+#define LOCAL_EGL_FORMAT_ASTC_8X5_QCOM 0x33E7
+#define LOCAL_EGL_FORMAT_ASTC_8X5_SRGB_QCOM 0x3405
+#define LOCAL_EGL_FORMAT_ASTC_8X6_QCOM 0x33E8
+#define LOCAL_EGL_FORMAT_ASTC_8X6_SRGB_QCOM 0x3406
+#define LOCAL_EGL_FORMAT_ASTC_8X8_QCOM 0x33E9
+#define LOCAL_EGL_FORMAT_ASTC_8X8_SRGB_QCOM 0x3407
+#define LOCAL_EGL_FORMAT_BGRA_8888_QCOM 0x3129
+#define LOCAL_EGL_FORMAT_BGRX_8888_QCOM 0x312A
+#define LOCAL_EGL_FORMAT_FLAG_MACROTILE_QCOM 0x33E1
+#define LOCAL_EGL_FORMAT_FLAG_QCOM 0x31CF
+#define LOCAL_EGL_FORMAT_FLAG_UBWC_QCOM 0x33E0
+#define LOCAL_EGL_FORMAT_IYUV_QCOM 0x31C7
+#define LOCAL_EGL_FORMAT_NV12_4R_QCOM 0x3412
+#define LOCAL_EGL_FORMAT_NV12_4R_UV_QCOM 0x3414
+#define LOCAL_EGL_FORMAT_NV12_4R_Y_QCOM 0x3413
+#define LOCAL_EGL_FORMAT_NV12_QCOM 0x31C2
+#define LOCAL_EGL_FORMAT_NV12_TILED_QCOM 0x3128
+#define LOCAL_EGL_FORMAT_NV12_UV_QCOM 0x3410
+#define LOCAL_EGL_FORMAT_NV12_Y_QCOM 0x340F
+#define LOCAL_EGL_FORMAT_NV21_QCOM 0x3127
+#define LOCAL_EGL_FORMAT_NV21_VU_QCOM 0x3411
+#define LOCAL_EGL_FORMAT_P010_QCOM 0x3415
+#define LOCAL_EGL_FORMAT_P010_UV_QCOM 0x3417
+#define LOCAL_EGL_FORMAT_P010_Y_QCOM 0x3416
+#define LOCAL_EGL_FORMAT_R8_QCOM 0x31C0
+#define LOCAL_EGL_FORMAT_RG88_QCOM 0x31C1
+#define LOCAL_EGL_FORMAT_RGBA_1010102_QCOM 0x31CE
+#define LOCAL_EGL_FORMAT_RGBA_16_FLOAT_QCOM 0x31CD
+#define LOCAL_EGL_FORMAT_RGBA_4444_QCOM 0x31CA
+#define LOCAL_EGL_FORMAT_RGBA_5551_QCOM 0x31C9
+#define LOCAL_EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
+#define LOCAL_EGL_FORMAT_RGBA_8888_KHR 0x30C3
+#define LOCAL_EGL_FORMAT_RGBA_8888_QCOM 0x3122
+#define LOCAL_EGL_FORMAT_RGBX_8888_QCOM 0x312F
+#define LOCAL_EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0
+#define LOCAL_EGL_FORMAT_RGB_565_KHR 0x30C1
+#define LOCAL_EGL_FORMAT_RGB_565_QCOM 0x3123
+#define LOCAL_EGL_FORMAT_RGB_888_QCOM 0x31C8
+#define LOCAL_EGL_FORMAT_RG_1616_FLOAT_QCOM 0x31CC
+#define LOCAL_EGL_FORMAT_R_16_FLOAT_QCOM 0x31CB
+#define LOCAL_EGL_FORMAT_SRGBA_8888_QCOM 0x31C4
+#define LOCAL_EGL_FORMAT_SRGBX_8888_QCOM 0x31C3
+#define LOCAL_EGL_FORMAT_TP10_QCOM 0x340E
+#define LOCAL_EGL_FORMAT_TP10_UV_QCOM 0x3419
+#define LOCAL_EGL_FORMAT_TP10_Y_QCOM 0x3418
+#define LOCAL_EGL_FORMAT_UYVY_QCOM 0x3125
+#define LOCAL_EGL_FORMAT_VYUY_QCOM 0x31C6
+#define LOCAL_EGL_FORMAT_YUYV_QCOM 0x3124
+#define LOCAL_EGL_FORMAT_YV12_QCOM 0x3126
+#define LOCAL_EGL_FORMAT_YVYU_QCOM 0x31C5
+#define LOCAL_EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147
+#define LOCAL_EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#define LOCAL_EGL_FRONT_BUFFER_EXT 0x3464
+#define LOCAL_EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x334C
+#define LOCAL_EGL_GENERIC_TOKEN_1_QCOM 0x3420
+#define LOCAL_EGL_GENERIC_TOKEN_2_QCOM 0x3421
+#define LOCAL_EGL_GENERIC_TOKEN_3_QCOM 0x3422
+#define LOCAL_EGL_GL_COLORSPACE 0x309D
+#define LOCAL_EGL_GL_COLORSPACE_BT2020_LINEAR_EXT 0x333F
+#define LOCAL_EGL_GL_COLORSPACE_BT2020_PQ_EXT 0x3340
+#define LOCAL_EGL_GL_COLORSPACE_DEFAULT_EXT 0x314D
+#define LOCAL_EGL_GL_COLORSPACE_DISPLAY_P3_EXT 0x3363
+#define LOCAL_EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT 0x3362
+#define LOCAL_EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT 0x3490
+#define LOCAL_EGL_GL_COLORSPACE_KHR 0x309D
+#define LOCAL_EGL_GL_COLORSPACE_LINEAR 0x308A
+#define LOCAL_EGL_GL_COLORSPACE_LINEAR_KHR 0x308A
+#define LOCAL_EGL_GL_COLORSPACE_SCRGB_EXT 0x3351
+#define LOCAL_EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT 0x3350
+#define LOCAL_EGL_GL_COLORSPACE_SRGB 0x3089
+#define LOCAL_EGL_GL_COLORSPACE_SRGB_KHR 0x3089
+#define LOCAL_EGL_GL_RENDERBUFFER 0x30B9
+#define LOCAL_EGL_GL_RENDERBUFFER_KHR 0x30B9
+#define LOCAL_EGL_GL_TEXTURE_2D 0x30B1
+#define LOCAL_EGL_GL_TEXTURE_2D_KHR 0x30B1
+#define LOCAL_EGL_GL_TEXTURE_3D 0x30B2
+#define LOCAL_EGL_GL_TEXTURE_3D_KHR 0x30B2
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
+#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7
+#define LOCAL_EGL_GL_TEXTURE_LEVEL 0x30BC
+#define LOCAL_EGL_GL_TEXTURE_LEVEL_KHR 0x30BC
+#define LOCAL_EGL_GL_TEXTURE_ZOFFSET 0x30BD
+#define LOCAL_EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD
+#define LOCAL_EGL_GPU_PERF_HINT_QCOM 0x32D0
+#define LOCAL_EGL_GREEN_SIZE 0x3023
+#define LOCAL_EGL_HEIGHT 0x3056
+#define LOCAL_EGL_HINT_PERSISTENT_QCOM 0x32D1
+#define LOCAL_EGL_HORIZONTAL_RESOLUTION 0x3090
+#define LOCAL_EGL_IMAGE_FORMAT_QCOM 0x3121
+#define LOCAL_EGL_IMAGE_NUM_PLANES_QCOM 0x32B0
+#define LOCAL_EGL_IMAGE_PLANE_DEPTH_0_QCOM 0x32B4
+#define LOCAL_EGL_IMAGE_PLANE_DEPTH_1_QCOM 0x32B5
+#define LOCAL_EGL_IMAGE_PLANE_DEPTH_2_QCOM 0x32B6
+#define LOCAL_EGL_IMAGE_PLANE_HEIGHT_0_QCOM 0x32BA
+#define LOCAL_EGL_IMAGE_PLANE_HEIGHT_1_QCOM 0x32BB
+#define LOCAL_EGL_IMAGE_PLANE_HEIGHT_2_QCOM 0x32BC
+#define LOCAL_EGL_IMAGE_PLANE_PITCH_0_QCOM 0x32B1
+#define LOCAL_EGL_IMAGE_PLANE_PITCH_1_QCOM 0x32B2
+#define LOCAL_EGL_IMAGE_PLANE_PITCH_2_QCOM 0x32B3
+#define LOCAL_EGL_IMAGE_PLANE_POINTER_0_QCOM 0x32BD
+#define LOCAL_EGL_IMAGE_PLANE_POINTER_1_QCOM 0x32BE
+#define LOCAL_EGL_IMAGE_PLANE_POINTER_2_QCOM 0x32BF
+#define LOCAL_EGL_IMAGE_PLANE_WIDTH_0_QCOM 0x32B7
+#define LOCAL_EGL_IMAGE_PLANE_WIDTH_1_QCOM 0x32B8
+#define LOCAL_EGL_IMAGE_PLANE_WIDTH_2_QCOM 0x32B9
+#define LOCAL_EGL_IMAGE_PRESERVED 0x30D2
+#define LOCAL_EGL_IMAGE_PRESERVED_KHR 0x30D2
+#define LOCAL_EGL_IMPORT_EXPLICIT_SYNC_EXT 0x3472
+#define LOCAL_EGL_IMPORT_IMPLICIT_SYNC_EXT 0x3471
+#define LOCAL_EGL_IMPORT_SYNC_TYPE_EXT 0x3470
+#define LOCAL_EGL_INTEROP_BIT_KHR 0x0010
+#define LOCAL_EGL_ITU_REC2020_EXT 0x3281
+#define LOCAL_EGL_ITU_REC601_EXT 0x327F
+#define LOCAL_EGL_ITU_REC709_EXT 0x3280
+#define LOCAL_EGL_LARGEST_PBUFFER 0x3058
+#define LOCAL_EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define LOCAL_EGL_LEFT_NV 0x336B
+#define LOCAL_EGL_LEVEL 0x3029
+#define LOCAL_EGL_LINUX_DMA_BUF_EXT 0x3270
+#define LOCAL_EGL_LINUX_DRM_FOURCC_EXT 0x3271
+#define LOCAL_EGL_LOCK_SURFACE_BIT_KHR 0x0080
+#define LOCAL_EGL_LOCK_USAGE_HINT_KHR 0x30C5
+#define LOCAL_EGL_LOSE_CONTEXT_ON_RESET 0x31BF
+#define LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
+#define LOCAL_EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
+#define LOCAL_EGL_LOWER_LEFT_KHR 0x30CE
+#define LOCAL_EGL_LUMINANCE_BUFFER 0x308F
+#define LOCAL_EGL_LUMINANCE_SIZE 0x303D
+#define LOCAL_EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4
+#define LOCAL_EGL_MATCH_FORMAT_KHR 0x3043
+#define LOCAL_EGL_MATCH_NATIVE_PIXMAP 0x3041
+#define LOCAL_EGL_MAX_PBUFFER_HEIGHT 0x302A
+#define LOCAL_EGL_MAX_PBUFFER_PIXELS 0x302B
+#define LOCAL_EGL_MAX_PBUFFER_WIDTH 0x302C
+#define LOCAL_EGL_MAX_STREAM_METADATA_BLOCKS_NV 0x3250
+#define LOCAL_EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV 0x3251
+#define LOCAL_EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV 0x3252
+#define LOCAL_EGL_MAX_SWAP_INTERVAL 0x303C
+#define LOCAL_EGL_METADATA0_SIZE_NV 0x3255
+#define LOCAL_EGL_METADATA0_TYPE_NV 0x3259
+#define LOCAL_EGL_METADATA1_SIZE_NV 0x3256
+#define LOCAL_EGL_METADATA1_TYPE_NV 0x325A
+#define LOCAL_EGL_METADATA2_SIZE_NV 0x3257
+#define LOCAL_EGL_METADATA2_TYPE_NV 0x325B
+#define LOCAL_EGL_METADATA3_SIZE_NV 0x3258
+#define LOCAL_EGL_METADATA3_TYPE_NV 0x325C
+#define LOCAL_EGL_METADATA_SCALING_EXT 50000
+#define LOCAL_EGL_MIN_SWAP_INTERVAL 0x303B
+#define LOCAL_EGL_MIPMAP_LEVEL 0x3083
+#define LOCAL_EGL_MIPMAP_TEXTURE 0x3082
+#define LOCAL_EGL_MULTISAMPLE_RESOLVE 0x3099
+#define LOCAL_EGL_MULTISAMPLE_RESOLVE_BOX 0x309B
+#define LOCAL_EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200
+#define LOCAL_EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A
+#define LOCAL_EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134
+#define LOCAL_EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#define LOCAL_EGL_NATIVE_BUFFER_ANDROID 0x3140
+#define LOCAL_EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
+#define LOCAL_EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG 0x3106
+#define LOCAL_EGL_NATIVE_BUFFER_TIZEN 0x32A0
+#define LOCAL_EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
+#define LOCAL_EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+#define LOCAL_EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+#define LOCAL_EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+#define LOCAL_EGL_NATIVE_PIXMAP_KHR 0x30B0
+#define LOCAL_EGL_NATIVE_RENDERABLE 0x302D
+#define LOCAL_EGL_NATIVE_SURFACE_TIZEN 0x32A1
+#define LOCAL_EGL_NATIVE_VISUAL_ID 0x302E
+#define LOCAL_EGL_NATIVE_VISUAL_TYPE 0x302F
+#define LOCAL_EGL_NEW_IMAGE_QCOM 0x3120
+#define LOCAL_EGL_NONE 0x3038
+#define LOCAL_EGL_NON_CONFORMANT_CONFIG 0x3051
+#define LOCAL_EGL_NOT_INITIALIZED 0x3001
+#define LOCAL_EGL_NO_CONFIG_KHR EGL_CAST(EGLConfig,0)
+#define LOCAL_EGL_NO_CONTEXT EGL_CAST(EGLContext,0)
+#define LOCAL_EGL_NO_DEVICE_EXT EGL_CAST(EGLDeviceEXT,0)
+#define LOCAL_EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0)
+#define LOCAL_EGL_NO_FILE_DESCRIPTOR_KHR EGL_CAST(EGLNativeFileDescriptorKHR,-1)
+#define LOCAL_EGL_NO_IMAGE EGL_CAST(EGLImage,0)
+#define LOCAL_EGL_NO_IMAGE_KHR EGL_CAST(EGLImageKHR,0)
+#define LOCAL_EGL_NO_NATIVE_FENCE_FD_ANDROID -1
+#define LOCAL_EGL_NO_OUTPUT_LAYER_EXT EGL_CAST(EGLOutputLayerEXT,0)
+#define LOCAL_EGL_NO_OUTPUT_PORT_EXT EGL_CAST(EGLOutputPortEXT,0)
+#define LOCAL_EGL_NO_RESET_NOTIFICATION 0x31BE
+#define LOCAL_EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
+#define LOCAL_EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
+#define LOCAL_EGL_NO_STREAM_KHR EGL_CAST(EGLStreamKHR,0)
+#define LOCAL_EGL_NO_SURFACE EGL_CAST(EGLSurface,0)
+#define LOCAL_EGL_NO_SYNC EGL_CAST(EGLSync,0)
+#define LOCAL_EGL_NO_SYNC_KHR EGL_CAST(EGLSyncKHR,0)
+#define LOCAL_EGL_NO_SYNC_NV EGL_CAST(EGLSyncNV,0)
+#define LOCAL_EGL_NO_TEXTURE 0x305C
+#define LOCAL_EGL_OBJECT_CONTEXT_KHR 0x33B2
+#define LOCAL_EGL_OBJECT_DISPLAY_KHR 0x33B1
+#define LOCAL_EGL_OBJECT_IMAGE_KHR 0x33B4
+#define LOCAL_EGL_OBJECT_STREAM_KHR 0x33B6
+#define LOCAL_EGL_OBJECT_SURFACE_KHR 0x33B3
+#define LOCAL_EGL_OBJECT_SYNC_KHR 0x33B5
+#define LOCAL_EGL_OBJECT_THREAD_KHR 0x33B0
+#define LOCAL_EGL_OPENGL_API 0x30A2
+#define LOCAL_EGL_OPENGL_BIT 0x0008
+#define LOCAL_EGL_OPENGL_ES2_BIT 0x0004
+#define LOCAL_EGL_OPENGL_ES3_BIT 0x00000040
+#define LOCAL_EGL_OPENGL_ES3_BIT_KHR 0x00000040
+#define LOCAL_EGL_OPENGL_ES_API 0x30A0
+#define LOCAL_EGL_OPENGL_ES_BIT 0x0001
+#define LOCAL_EGL_OPENMAX_IL_BIT_KHR 0x0020
+#define LOCAL_EGL_OPENVG_API 0x30A1
+#define LOCAL_EGL_OPENVG_BIT 0x0002
+#define LOCAL_EGL_OPENVG_IMAGE 0x3096
+#define LOCAL_EGL_OPENWF_DEVICE_ID_EXT 0x3237
+#define LOCAL_EGL_OPENWF_PIPELINE_ID_EXT 0x3238
+#define LOCAL_EGL_OPENWF_PORT_ID_EXT 0x3239
+#define LOCAL_EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100
+#define LOCAL_EGL_PBUFFER_BIT 0x0001
+#define LOCAL_EGL_PBUFFER_IMAGE_BIT_TAO 0x0008
+#define LOCAL_EGL_PBUFFER_PALETTE_IMAGE_BIT_TAO 0x0010
+#define LOCAL_EGL_PENDING_FRAME_NV 0x3329
+#define LOCAL_EGL_PENDING_METADATA_NV 0x3328
+#define LOCAL_EGL_PIXEL_ASPECT_RATIO 0x3092
+#define LOCAL_EGL_PIXMAP_BIT 0x0002
+#define LOCAL_EGL_PLATFORM_ANDROID_KHR 0x3141
+#define LOCAL_EGL_PLATFORM_DEVICE_EXT 0x313F
+#define LOCAL_EGL_PLATFORM_GBM_KHR 0x31D7
+#define LOCAL_EGL_PLATFORM_GBM_MESA 0x31D7
+#define LOCAL_EGL_PLATFORM_SURFACELESS_MESA 0x31DD
+#define LOCAL_EGL_PLATFORM_WAYLAND_EXT 0x31D8
+#define LOCAL_EGL_PLATFORM_WAYLAND_KHR 0x31D8
+#define LOCAL_EGL_PLATFORM_X11_EXT 0x31D5
+#define LOCAL_EGL_PLATFORM_X11_KHR 0x31D5
+#define LOCAL_EGL_PLATFORM_X11_SCREEN_EXT 0x31D6
+#define LOCAL_EGL_PLATFORM_X11_SCREEN_KHR 0x31D6
+#define LOCAL_EGL_PLATFORM_XCB_EXT 0x31DC
+#define LOCAL_EGL_PLATFORM_XCB_SCREEN_EXT 0x31DE
+#define LOCAL_EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE
+#define LOCAL_EGL_PRIMARY_COMPOSITOR_CONTEXT_EXT 0x3460
+#define LOCAL_EGL_PRODUCER_AUTO_ORIENTATION_NV 0x336A
+#define LOCAL_EGL_PRODUCER_FRAME_KHR 0x3212
+#define LOCAL_EGL_PRODUCER_MAX_FRAME_HINT_NV 0x3337
+#define LOCAL_EGL_PRODUCER_METADATA_NV 0x3253
+#define LOCAL_EGL_PROTECTED_CONTENT_EXT 0x32C0
+#define LOCAL_EGL_QUADRUPLE_BUFFER_NV 0x3231
+#define LOCAL_EGL_READ 0x305A
+#define LOCAL_EGL_READS_DONE_TIME_ANDROID 0x343C
+#define LOCAL_EGL_READ_SURFACE_BIT_KHR 0x0001
+#define LOCAL_EGL_RECORDABLE_ANDROID 0x3142
+#define LOCAL_EGL_RED_SIZE 0x3024
+#define LOCAL_EGL_RENDERABLE_TYPE 0x3040
+#define LOCAL_EGL_RENDERER_EXT 0x335F
+#define LOCAL_EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define LOCAL_EGL_RENDER_BUFFER 0x3086
+#define LOCAL_EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define LOCAL_EGL_RGB_BUFFER 0x308E
+#define LOCAL_EGL_RIGHT_NV 0x336C
+#define LOCAL_EGL_SAMPLES 0x3031
+#define LOCAL_EGL_SAMPLE_BUFFERS 0x3032
+#define LOCAL_EGL_SAMPLE_RANGE_HINT_EXT 0x327C
+#define LOCAL_EGL_SHARED_IMAGE_NOK 0x30DA
+#define LOCAL_EGL_SIGNALED 0x30F2
+#define LOCAL_EGL_SIGNALED_KHR 0x30F2
+#define LOCAL_EGL_SIGNALED_NV 0x30E8
+#define LOCAL_EGL_SINGLE_BUFFER 0x3085
+#define LOCAL_EGL_SLOW_CONFIG 0x3050
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT 0x3345
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT 0x3346
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT 0x3343
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT 0x3344
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT 0x3341
+#define LOCAL_EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT 0x3342
+#define LOCAL_EGL_SMPTE2086_MAX_LUMINANCE_EXT 0x3349
+#define LOCAL_EGL_SMPTE2086_MIN_LUMINANCE_EXT 0x334A
+#define LOCAL_EGL_SMPTE2086_WHITE_POINT_X_EXT 0x3347
+#define LOCAL_EGL_SMPTE2086_WHITE_POINT_Y_EXT 0x3348
+#define LOCAL_EGL_SOCKET_HANDLE_NV 0x324C
+#define LOCAL_EGL_SOCKET_TYPE_INET_NV 0x324F
+#define LOCAL_EGL_SOCKET_TYPE_NV 0x324D
+#define LOCAL_EGL_SOCKET_TYPE_UNIX_NV 0x324E
+#define LOCAL_EGL_STENCIL_SIZE 0x3026
+#define LOCAL_EGL_STREAM_BIT_KHR 0x0800
+#define LOCAL_EGL_STREAM_CONSUMER_IMAGE_NV 0x3373
+#define LOCAL_EGL_STREAM_CONSUMER_NV 0x3248
+#define LOCAL_EGL_STREAM_CROSS_DISPLAY_NV 0x334E
+#define LOCAL_EGL_STREAM_CROSS_OBJECT_NV 0x334D
+#define LOCAL_EGL_STREAM_CROSS_PARTITION_NV 0x323F
+#define LOCAL_EGL_STREAM_CROSS_PROCESS_NV 0x3245
+#define LOCAL_EGL_STREAM_CROSS_SYSTEM_NV 0x334F
+#define LOCAL_EGL_STREAM_DMA_NV 0x3371
+#define LOCAL_EGL_STREAM_DMA_SERVER_NV 0x3372
+#define LOCAL_EGL_STREAM_ENDPOINT_NV 0x3243
+#define LOCAL_EGL_STREAM_FIFO_LENGTH_KHR 0x31FC
+#define LOCAL_EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336
+#define LOCAL_EGL_STREAM_FRAME_MAJOR_AXIS_NV 0x3368
+#define LOCAL_EGL_STREAM_FRAME_ORIGIN_X_NV 0x3366
+#define LOCAL_EGL_STREAM_FRAME_ORIGIN_Y_NV 0x3367
+#define LOCAL_EGL_STREAM_IMAGE_ADD_NV 0x3374
+#define LOCAL_EGL_STREAM_IMAGE_AVAILABLE_NV 0x3376
+#define LOCAL_EGL_STREAM_IMAGE_REMOVE_NV 0x3375
+#define LOCAL_EGL_STREAM_LOCAL_NV 0x3244
+#define LOCAL_EGL_STREAM_PRODUCER_NV 0x3247
+#define LOCAL_EGL_STREAM_PROTOCOL_FD_NV 0x3246
+#define LOCAL_EGL_STREAM_PROTOCOL_NV 0x3242
+#define LOCAL_EGL_STREAM_PROTOCOL_SOCKET_NV 0x324B
+#define LOCAL_EGL_STREAM_STATE_CONNECTING_KHR 0x3216
+#define LOCAL_EGL_STREAM_STATE_CREATED_KHR 0x3215
+#define LOCAL_EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A
+#define LOCAL_EGL_STREAM_STATE_EMPTY_KHR 0x3217
+#define LOCAL_EGL_STREAM_STATE_INITIALIZING_NV 0x3240
+#define LOCAL_EGL_STREAM_STATE_KHR 0x3214
+#define LOCAL_EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218
+#define LOCAL_EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219
+#define LOCAL_EGL_STREAM_TIME_CONSUMER_KHR 0x31FE
+#define LOCAL_EGL_STREAM_TIME_NOW_KHR 0x31FD
+#define LOCAL_EGL_STREAM_TIME_PENDING_NV 0x332A
+#define LOCAL_EGL_STREAM_TIME_PRODUCER_KHR 0x31FF
+#define LOCAL_EGL_STREAM_TYPE_NV 0x3241
+#define LOCAL_EGL_SUCCESS 0x3000
+#define LOCAL_EGL_SUPPORT_RESET_NV 0x3334
+#define LOCAL_EGL_SUPPORT_REUSE_NV 0x3335
+#define LOCAL_EGL_SURFACE_TYPE 0x3033
+#define LOCAL_EGL_SWAP_BEHAVIOR 0x3093
+#define LOCAL_EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400
+#define LOCAL_EGL_SWAP_INTERVAL_EXT 0x322F
+#define LOCAL_EGL_SYNC_CLIENT_EXT 0x3364
+#define LOCAL_EGL_SYNC_CLIENT_SIGNAL_EXT 0x3365
+#define LOCAL_EGL_SYNC_CL_EVENT 0x30FE
+#define LOCAL_EGL_SYNC_CL_EVENT_COMPLETE 0x30FF
+#define LOCAL_EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF
+#define LOCAL_EGL_SYNC_CL_EVENT_KHR 0x30FE
+#define LOCAL_EGL_SYNC_CONDITION 0x30F8
+#define LOCAL_EGL_SYNC_CONDITION_KHR 0x30F8
+#define LOCAL_EGL_SYNC_CONDITION_NV 0x30EE
+#define LOCAL_EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D
+#define LOCAL_EGL_SYNC_CUDA_EVENT_NV 0x323C
+#define LOCAL_EGL_SYNC_FENCE 0x30F9
+#define LOCAL_EGL_SYNC_FENCE_KHR 0x30F9
+#define LOCAL_EGL_SYNC_FENCE_NV 0x30EF
+#define LOCAL_EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001
+#define LOCAL_EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001
+#define LOCAL_EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001
+#define LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
+#define LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
+#define LOCAL_EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146
+#define LOCAL_EGL_SYNC_NEW_FRAME_NV 0x321F
+#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0
+#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0
+#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6
+#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM 0x328A
+#define LOCAL_EGL_SYNC_REUSABLE_KHR 0x30FA
+#define LOCAL_EGL_SYNC_STATUS 0x30F1
+#define LOCAL_EGL_SYNC_STATUS_KHR 0x30F1
+#define LOCAL_EGL_SYNC_STATUS_NV 0x30E7
+#define LOCAL_EGL_SYNC_TYPE 0x30F7
+#define LOCAL_EGL_SYNC_TYPE_KHR 0x30F7
+#define LOCAL_EGL_SYNC_TYPE_NV 0x30ED
+#define LOCAL_EGL_TEXTURE_2D 0x305F
+#define LOCAL_EGL_TEXTURE_EXTERNAL_WL 0x31DA
+#define LOCAL_EGL_TEXTURE_FORMAT 0x3080
+#define LOCAL_EGL_TEXTURE_RGB 0x305D
+#define LOCAL_EGL_TEXTURE_RGBA 0x305E
+#define LOCAL_EGL_TEXTURE_TARGET 0x3081
+#define LOCAL_EGL_TEXTURE_Y_UV_WL 0x31D8
+#define LOCAL_EGL_TEXTURE_Y_U_V_WL 0x31D7
+#define LOCAL_EGL_TEXTURE_Y_XUXV_WL 0x31D9
+#define LOCAL_EGL_TIMEOUT_EXPIRED 0x30F5
+#define LOCAL_EGL_TIMEOUT_EXPIRED_KHR 0x30F5
+#define LOCAL_EGL_TIMEOUT_EXPIRED_NV 0x30EB
+#define LOCAL_EGL_TIMESTAMPS_ANDROID 0x3430
+#define LOCAL_EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID,-1)
+#define LOCAL_EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID,-2)
+#define LOCAL_EGL_TOP_NV 0x336D
+#define LOCAL_EGL_TRACK_REFERENCES_KHR 0x3352
+#define LOCAL_EGL_TRANSPARENT_BLUE_VALUE 0x3035
+#define LOCAL_EGL_TRANSPARENT_GREEN_VALUE 0x3036
+#define LOCAL_EGL_TRANSPARENT_RED_VALUE 0x3037
+#define LOCAL_EGL_TRANSPARENT_RGB 0x3052
+#define LOCAL_EGL_TRANSPARENT_TYPE 0x3034
+#define LOCAL_EGL_TRIPLE_BUFFER_NV 0x3230
+#define LOCAL_EGL_TRUE 1
+#define LOCAL_EGL_UNKNOWN EGL_CAST(EGLint,-1)
+#define LOCAL_EGL_UNSIGNALED 0x30F3
+#define LOCAL_EGL_UNSIGNALED_KHR 0x30F3
+#define LOCAL_EGL_UNSIGNALED_NV 0x30E9
+#define LOCAL_EGL_UPPER_LEFT_KHR 0x30CF
+#define LOCAL_EGL_VENDOR 0x3053
+#define LOCAL_EGL_VERSION 0x3054
+#define LOCAL_EGL_VERTICAL_RESOLUTION 0x3091
+#define LOCAL_EGL_VG_ALPHA_FORMAT 0x3088
+#define LOCAL_EGL_VG_ALPHA_FORMAT_NONPRE 0x308B
+#define LOCAL_EGL_VG_ALPHA_FORMAT_PRE 0x308C
+#define LOCAL_EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040
+#define LOCAL_EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040
+#define LOCAL_EGL_VG_COLORSPACE 0x3087
+#define LOCAL_EGL_VG_COLORSPACE_LINEAR 0x308A
+#define LOCAL_EGL_VG_COLORSPACE_LINEAR_BIT 0x0020
+#define LOCAL_EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020
+#define LOCAL_EGL_VG_COLORSPACE_sRGB 0x3089
+#define LOCAL_EGL_VG_PARENT_IMAGE_KHR 0x30BA
+#define LOCAL_EGL_WAYLAND_BUFFER_WL 0x31D5
+#define LOCAL_EGL_WAYLAND_PLANE_WL 0x31D6
+#define LOCAL_EGL_WAYLAND_Y_INVERTED_WL 0x31DB
+#define LOCAL_EGL_WIDTH 0x3057
+#define LOCAL_EGL_WINDOW_BIT 0x0004
+#define LOCAL_EGL_WRITE_SURFACE_BIT_KHR 0x0002
+#define LOCAL_EGL_X_AXIS_NV 0x336F
+#define LOCAL_EGL_YUV_BUFFER_EXT 0x3300
+#define LOCAL_EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D
+#define LOCAL_EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285
+#define LOCAL_EGL_YUV_CHROMA_SITING_0_EXT 0x3284
+#define LOCAL_EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E
+#define LOCAL_EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B
+#define LOCAL_EGL_YUV_CSC_STANDARD_2020_EXT 0x330D
+#define LOCAL_EGL_YUV_CSC_STANDARD_601_EXT 0x330B
+#define LOCAL_EGL_YUV_CSC_STANDARD_709_EXT 0x330C
+#define LOCAL_EGL_YUV_CSC_STANDARD_EXT 0x330A
+#define LOCAL_EGL_YUV_DEPTH_RANGE_EXT 0x3317
+#define LOCAL_EGL_YUV_DEPTH_RANGE_FULL_EXT 0x3319
+#define LOCAL_EGL_YUV_DEPTH_RANGE_LIMITED_EXT 0x3318
+#define LOCAL_EGL_YUV_FULL_RANGE_EXT 0x3282
+#define LOCAL_EGL_YUV_NARROW_RANGE_EXT 0x3283
+#define LOCAL_EGL_YUV_NUMBER_OF_PLANES_EXT 0x3311
+#define LOCAL_EGL_YUV_ORDER_AYUV_EXT 0x3308
+#define LOCAL_EGL_YUV_ORDER_EXT 0x3301
+#define LOCAL_EGL_YUV_ORDER_UYVY_EXT 0x3305
+#define LOCAL_EGL_YUV_ORDER_VYUY_EXT 0x3307
+#define LOCAL_EGL_YUV_ORDER_YUV_EXT 0x3302
+#define LOCAL_EGL_YUV_ORDER_YUYV_EXT 0x3304
+#define LOCAL_EGL_YUV_ORDER_YVU_EXT 0x3303
+#define LOCAL_EGL_YUV_ORDER_YVYU_EXT 0x3306
+#define LOCAL_EGL_YUV_PLANE0_TEXTURE_UNIT_NV 0x332C
+#define LOCAL_EGL_YUV_PLANE1_TEXTURE_UNIT_NV 0x332D
+#define LOCAL_EGL_YUV_PLANE2_TEXTURE_UNIT_NV 0x332E
+#define LOCAL_EGL_YUV_PLANE_BPP_0_EXT 0x331B
+#define LOCAL_EGL_YUV_PLANE_BPP_10_EXT 0x331D
+#define LOCAL_EGL_YUV_PLANE_BPP_8_EXT 0x331C
+#define LOCAL_EGL_YUV_PLANE_BPP_EXT 0x331A
+#define LOCAL_EGL_YUV_SUBSAMPLE_4_2_0_EXT 0x3313
+#define LOCAL_EGL_YUV_SUBSAMPLE_4_2_2_EXT 0x3314
+#define LOCAL_EGL_YUV_SUBSAMPLE_4_4_4_EXT 0x3315
+#define LOCAL_EGL_YUV_SUBSAMPLE_EXT 0x3312
+#define LOCAL_EGL_Y_AXIS_NV 0x3370
+#define LOCAL_EGL_Y_INVERTED_NOK 0x307F
+
+// GLX
+#define LOCAL_GLX_3DFX_FULLSCREEN_MODE_MESA 0x2
+#define LOCAL_GLX_3DFX_WINDOW_MODE_MESA 0x1
+#define LOCAL_GLX_ACCUM_ALPHA_SIZE 17
+#define LOCAL_GLX_ACCUM_BLUE_SIZE 16
+#define LOCAL_GLX_ACCUM_BUFFER_BIT 0x00000080
+#define LOCAL_GLX_ACCUM_BUFFER_BIT_SGIX 0x00000080
+#define LOCAL_GLX_ACCUM_GREEN_SIZE 15
+#define LOCAL_GLX_ACCUM_RED_SIZE 14
+#define LOCAL_GLX_ALPHA_SIZE 11
+#define LOCAL_GLX_AUX0_EXT 0x20E2
+#define LOCAL_GLX_AUX1_EXT 0x20E3
+#define LOCAL_GLX_AUX2_EXT 0x20E4
+#define LOCAL_GLX_AUX3_EXT 0x20E5
+#define LOCAL_GLX_AUX4_EXT 0x20E6
+#define LOCAL_GLX_AUX5_EXT 0x20E7
+#define LOCAL_GLX_AUX6_EXT 0x20E8
+#define LOCAL_GLX_AUX7_EXT 0x20E9
+#define LOCAL_GLX_AUX8_EXT 0x20EA
+#define LOCAL_GLX_AUX9_EXT 0x20EB
+#define LOCAL_GLX_AUX_BUFFERS 7
+#define LOCAL_GLX_AUX_BUFFERS_BIT 0x00000010
+#define LOCAL_GLX_AUX_BUFFERS_BIT_SGIX 0x00000010
+#define LOCAL_GLX_BACK_BUFFER_AGE_EXT 0x20F4
+#define LOCAL_GLX_BACK_EXT 0x20E0
+#define LOCAL_GLX_BACK_LEFT_BUFFER_BIT 0x00000004
+#define LOCAL_GLX_BACK_LEFT_BUFFER_BIT_SGIX 0x00000004
+#define LOCAL_GLX_BACK_LEFT_EXT 0x20E0
+#define LOCAL_GLX_BACK_RIGHT_BUFFER_BIT 0x00000008
+#define LOCAL_GLX_BACK_RIGHT_BUFFER_BIT_SGIX 0x00000008
+#define LOCAL_GLX_BACK_RIGHT_EXT 0x20E1
+#define LOCAL_GLX_BAD_ATTRIBUTE 2
+#define LOCAL_GLX_BAD_CONTEXT 5
+#define LOCAL_GLX_BAD_ENUM 7
+#define LOCAL_GLX_BAD_HYPERPIPE_CONFIG_SGIX 91
+#define LOCAL_GLX_BAD_HYPERPIPE_SGIX 92
+#define LOCAL_GLX_BAD_SCREEN 1
+#define LOCAL_GLX_BAD_VALUE 6
+#define LOCAL_GLX_BAD_VISUAL 4
+#define LOCAL_GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2
+#define LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
+#define LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0
+#define LOCAL_GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
+#define LOCAL_GLX_BLENDED_RGBA_SGIS 0x8025
+#define LOCAL_GLX_BLUE_SIZE 10
+#define LOCAL_GLX_BUFFER_CLOBBER_MASK_SGIX 0x08000000
+#define LOCAL_GLX_BUFFER_SIZE 2
+#define LOCAL_GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK 0x04000000
+#define LOCAL_GLX_BufferSwapComplete 1
+#define LOCAL_GLX_COLOR_INDEX_BIT 0x00000002
+#define LOCAL_GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define LOCAL_GLX_COLOR_INDEX_TYPE 0x8015
+#define LOCAL_GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+#define LOCAL_GLX_COLOR_SAMPLES_NV 0x20B3
+#define LOCAL_GLX_CONFIG_CAVEAT 0x20
+#define LOCAL_GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
+#define LOCAL_GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define LOCAL_GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define LOCAL_GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#define LOCAL_GLX_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define LOCAL_GLX_CONTEXT_FLAGS_ARB 0x2094
+#define LOCAL_GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define LOCAL_GLX_CONTEXT_MULTIGPU_ATTRIB_AFR_NV 0x20AC
+#define LOCAL_GLX_CONTEXT_MULTIGPU_ATTRIB_MULTICAST_NV 0x20AD
+#define LOCAL_GLX_CONTEXT_MULTIGPU_ATTRIB_MULTI_DISPLAY_MULTICAST_NV 0x20AE
+#define LOCAL_GLX_CONTEXT_MULTIGPU_ATTRIB_NV 0x20AA
+#define LOCAL_GLX_CONTEXT_MULTIGPU_ATTRIB_SINGLE_NV 0x20AB
+#define LOCAL_GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
+#define LOCAL_GLX_CONTEXT_PRIORITY_HIGH_EXT 0x3101
+#define LOCAL_GLX_CONTEXT_PRIORITY_LEVEL_EXT 0x3100
+#define LOCAL_GLX_CONTEXT_PRIORITY_LOW_EXT 0x3103
+#define LOCAL_GLX_CONTEXT_PRIORITY_MEDIUM_EXT 0x3102
+#define LOCAL_GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define LOCAL_GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define LOCAL_GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#define LOCAL_GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define LOCAL_GLX_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+#define LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define LOCAL_GLX_COPY_COMPLETE_INTEL 0x8181
+#define LOCAL_GLX_COVERAGE_SAMPLES_NV 100001
+#define LOCAL_GLX_DAMAGED 0x8020
+#define LOCAL_GLX_DAMAGED_SGIX 0x8020
+#define LOCAL_GLX_DEPTH_BUFFER_BIT 0x00000020
+#define LOCAL_GLX_DEPTH_BUFFER_BIT_SGIX 0x00000020
+#define LOCAL_GLX_DEPTH_SIZE 12
+#define LOCAL_GLX_DEVICE_ID_NV 0x20CD
+#define LOCAL_GLX_DIGITAL_MEDIA_PBUFFER_SGIX 0x8024
+#define LOCAL_GLX_DIRECT_COLOR 0x8003
+#define LOCAL_GLX_DIRECT_COLOR_EXT 0x8003
+#define LOCAL_GLX_DONT_CARE 0xFFFFFFFF
+#define LOCAL_GLX_DOUBLEBUFFER 5
+#define LOCAL_GLX_DRAWABLE_TYPE 0x8010
+#define LOCAL_GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define LOCAL_GLX_EVENT_MASK 0x801F
+#define LOCAL_GLX_EVENT_MASK_SGIX 0x801F
+#define LOCAL_GLX_EXCHANGE_COMPLETE_INTEL 0x8180
+#define LOCAL_GLX_EXTENSIONS 0x3
+#define LOCAL_GLX_EXTENSION_NAME "GLX"
+#define LOCAL_GLX_FBCONFIG_ID 0x8013
+#define LOCAL_GLX_FBCONFIG_ID_SGIX 0x8013
+#define LOCAL_GLX_FLIP_COMPLETE_INTEL 0x8182
+#define LOCAL_GLX_FLOAT_COMPONENTS_NV 0x20B0
+#define LOCAL_GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+#define LOCAL_GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20B2
+#define LOCAL_GLX_FRONT_EXT 0x20DE
+#define LOCAL_GLX_FRONT_LEFT_BUFFER_BIT 0x00000001
+#define LOCAL_GLX_FRONT_LEFT_BUFFER_BIT_SGIX 0x00000001
+#define LOCAL_GLX_FRONT_LEFT_EXT 0x20DE
+#define LOCAL_GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002
+#define LOCAL_GLX_FRONT_RIGHT_BUFFER_BIT_SGIX 0x00000002
+#define LOCAL_GLX_FRONT_RIGHT_EXT 0x20DF
+#define LOCAL_GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7
+#define LOCAL_GLX_GPU_CLOCK_AMD 0x21A4
+#define LOCAL_GLX_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define LOCAL_GLX_GPU_NUM_PIPES_AMD 0x21A5
+#define LOCAL_GLX_GPU_NUM_RB_AMD 0x21A7
+#define LOCAL_GLX_GPU_NUM_SIMD_AMD 0x21A6
+#define LOCAL_GLX_GPU_NUM_SPI_AMD 0x21A8
+#define LOCAL_GLX_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define LOCAL_GLX_GPU_RAM_AMD 0x21A3
+#define LOCAL_GLX_GPU_RENDERER_STRING_AMD 0x1F01
+#define LOCAL_GLX_GPU_VENDOR_AMD 0x1F00
+#define LOCAL_GLX_GRAY_SCALE 0x8006
+#define LOCAL_GLX_GRAY_SCALE_EXT 0x8006
+#define LOCAL_GLX_GREEN_SIZE 9
+#define LOCAL_GLX_HEIGHT 0x801E
+#define LOCAL_GLX_HEIGHT_SGIX 0x801E
+#define LOCAL_GLX_HYPERPIPE_DISPLAY_PIPE_SGIX 0x00000001
+#define LOCAL_GLX_HYPERPIPE_ID_SGIX 0x8030
+#define LOCAL_GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX 80
+#define LOCAL_GLX_HYPERPIPE_PIXEL_AVERAGE_SGIX 0x00000004
+#define LOCAL_GLX_HYPERPIPE_RENDER_PIPE_SGIX 0x00000002
+#define LOCAL_GLX_HYPERPIPE_STEREO_SGIX 0x00000003
+#define LOCAL_GLX_LARGEST_PBUFFER 0x801C
+#define LOCAL_GLX_LARGEST_PBUFFER_SGIX 0x801C
+#define LOCAL_GLX_LATE_SWAPS_TEAR_EXT 0x20F3
+#define LOCAL_GLX_LEVEL 3
+#define LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define LOCAL_GLX_MAX_PBUFFER_HEIGHT 0x8017
+#define LOCAL_GLX_MAX_PBUFFER_HEIGHT_SGIX 0x8017
+#define LOCAL_GLX_MAX_PBUFFER_PIXELS 0x8018
+#define LOCAL_GLX_MAX_PBUFFER_PIXELS_SGIX 0x8018
+#define LOCAL_GLX_MAX_PBUFFER_WIDTH 0x8016
+#define LOCAL_GLX_MAX_PBUFFER_WIDTH_SGIX 0x8016
+#define LOCAL_GLX_MAX_SWAP_INTERVAL_EXT 0x20F2
+#define LOCAL_GLX_MIPMAP_TEXTURE_EXT 0x20D7
+#define LOCAL_GLX_MULTISAMPLE_SUB_RECT_HEIGHT_SGIS 0x8027
+#define LOCAL_GLX_MULTISAMPLE_SUB_RECT_WIDTH_SGIS 0x8026
+#define LOCAL_GLX_NONE 0x8000
+#define LOCAL_GLX_NONE_EXT 0x8000
+#define LOCAL_GLX_NON_CONFORMANT_CONFIG 0x800D
+#define LOCAL_GLX_NON_CONFORMANT_VISUAL_EXT 0x800D
+#define LOCAL_GLX_NO_EXTENSION 3
+#define LOCAL_GLX_NO_RESET_NOTIFICATION_ARB 0x8261
+#define LOCAL_GLX_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+#define LOCAL_GLX_NUM_VIDEO_SLOTS_NV 0x20F0
+#define LOCAL_GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX 0x801A
+#define LOCAL_GLX_OPTIMAL_PBUFFER_WIDTH_SGIX 0x8019
+#define LOCAL_GLX_PBUFFER 0x8023
+#define LOCAL_GLX_PBUFFER_BIT 0x00000004
+#define LOCAL_GLX_PBUFFER_BIT_SGIX 0x00000004
+#define LOCAL_GLX_PBUFFER_CLOBBER_MASK 0x08000000
+#define LOCAL_GLX_PBUFFER_HEIGHT 0x8040
+#define LOCAL_GLX_PBUFFER_SGIX 0x8023
+#define LOCAL_GLX_PBUFFER_WIDTH 0x8041
+#define LOCAL_GLX_PIPE_RECT_LIMITS_SGIX 0x00000002
+#define LOCAL_GLX_PIPE_RECT_SGIX 0x00000001
+#define LOCAL_GLX_PIXMAP_BIT 0x00000002
+#define LOCAL_GLX_PIXMAP_BIT_SGIX 0x00000002
+#define LOCAL_GLX_PRESERVED_CONTENTS 0x801B
+#define LOCAL_GLX_PRESERVED_CONTENTS_SGIX 0x801B
+#define LOCAL_GLX_PSEUDO_COLOR 0x8004
+#define LOCAL_GLX_PSEUDO_COLOR_EXT 0x8004
+#define LOCAL_GLX_PbufferClobber 0
+#define LOCAL_GLX_RED_SIZE 8
+#define LOCAL_GLX_RENDERER_ACCELERATED_MESA 0x8186
+#define LOCAL_GLX_RENDERER_DEVICE_ID_MESA 0x8184
+#define LOCAL_GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B
+#define LOCAL_GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A
+#define LOCAL_GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D
+#define LOCAL_GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C
+#define LOCAL_GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189
+#define LOCAL_GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188
+#define LOCAL_GLX_RENDERER_VENDOR_ID_MESA 0x8183
+#define LOCAL_GLX_RENDERER_VERSION_MESA 0x8185
+#define LOCAL_GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187
+#define LOCAL_GLX_RENDER_TYPE 0x8011
+#define LOCAL_GLX_RENDER_TYPE_SGIX 0x8011
+#define LOCAL_GLX_RGBA 4
+#define LOCAL_GLX_RGBA_BIT 0x00000001
+#define LOCAL_GLX_RGBA_BIT_SGIX 0x00000001
+#define LOCAL_GLX_RGBA_FLOAT_BIT_ARB 0x00000004
+#define LOCAL_GLX_RGBA_FLOAT_TYPE_ARB 0x20B9
+#define LOCAL_GLX_RGBA_TYPE 0x8014
+#define LOCAL_GLX_RGBA_TYPE_SGIX 0x8014
+#define LOCAL_GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT 0x00000008
+#define LOCAL_GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT 0x20B1
+#define LOCAL_GLX_SAMPLES 100001
+#define LOCAL_GLX_SAMPLES_3DFX 0x8051
+#define LOCAL_GLX_SAMPLES_ARB 100001
+#define LOCAL_GLX_SAMPLES_SGIS 100001
+#define LOCAL_GLX_SAMPLE_BUFFERS 100000
+#define LOCAL_GLX_SAMPLE_BUFFERS_3DFX 0x8050
+#define LOCAL_GLX_SAMPLE_BUFFERS_ARB 100000
+#define LOCAL_GLX_SAMPLE_BUFFERS_BIT_SGIX 0x00000100
+#define LOCAL_GLX_SAMPLE_BUFFERS_SGIS 100000
+#define LOCAL_GLX_SAVED 0x8021
+#define LOCAL_GLX_SAVED_SGIX 0x8021
+#define LOCAL_GLX_SCREEN 0x800C
+#define LOCAL_GLX_SCREEN_EXT 0x800C
+#define LOCAL_GLX_SHARE_CONTEXT_EXT 0x800A
+#define LOCAL_GLX_SLOW_CONFIG 0x8001
+#define LOCAL_GLX_SLOW_VISUAL_EXT 0x8001
+#define LOCAL_GLX_STATIC_COLOR 0x8005
+#define LOCAL_GLX_STATIC_COLOR_EXT 0x8005
+#define LOCAL_GLX_STATIC_GRAY 0x8007
+#define LOCAL_GLX_STATIC_GRAY_EXT 0x8007
+#define LOCAL_GLX_STENCIL_BUFFER_BIT 0x00000040
+#define LOCAL_GLX_STENCIL_BUFFER_BIT_SGIX 0x00000040
+#define LOCAL_GLX_STENCIL_SIZE 13
+#define LOCAL_GLX_STEREO 6
+#define LOCAL_GLX_STEREO_NOTIFY_EXT 0x00000000
+#define LOCAL_GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
+#define LOCAL_GLX_STEREO_TREE_EXT 0x20F5
+#define LOCAL_GLX_SWAP_COPY_OML 0x8062
+#define LOCAL_GLX_SWAP_EXCHANGE_OML 0x8061
+#define LOCAL_GLX_SWAP_INTERVAL_EXT 0x20F1
+#define LOCAL_GLX_SWAP_METHOD_OML 0x8060
+#define LOCAL_GLX_SWAP_UNDEFINED_OML 0x8063
+#define LOCAL_GLX_SYNC_FRAME_SGIX 0x00000000
+#define LOCAL_GLX_SYNC_SWAP_SGIX 0x00000001
+#define LOCAL_GLX_TEXTURE_1D_BIT_EXT 0x00000001
+#define LOCAL_GLX_TEXTURE_1D_EXT 0x20DB
+#define LOCAL_GLX_TEXTURE_2D_BIT_EXT 0x00000002
+#define LOCAL_GLX_TEXTURE_2D_EXT 0x20DC
+#define LOCAL_GLX_TEXTURE_FORMAT_EXT 0x20D5
+#define LOCAL_GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8
+#define LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA
+#define LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9
+#define LOCAL_GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004
+#define LOCAL_GLX_TEXTURE_RECTANGLE_EXT 0x20DD
+#define LOCAL_GLX_TEXTURE_TARGET_EXT 0x20D6
+#define LOCAL_GLX_TRANSPARENT_ALPHA_VALUE 0x28
+#define LOCAL_GLX_TRANSPARENT_ALPHA_VALUE_EXT 0x28
+#define LOCAL_GLX_TRANSPARENT_BLUE_VALUE 0x27
+#define LOCAL_GLX_TRANSPARENT_BLUE_VALUE_EXT 0x27
+#define LOCAL_GLX_TRANSPARENT_GREEN_VALUE 0x26
+#define LOCAL_GLX_TRANSPARENT_GREEN_VALUE_EXT 0x26
+#define LOCAL_GLX_TRANSPARENT_INDEX 0x8009
+#define LOCAL_GLX_TRANSPARENT_INDEX_EXT 0x8009
+#define LOCAL_GLX_TRANSPARENT_INDEX_VALUE 0x24
+#define LOCAL_GLX_TRANSPARENT_INDEX_VALUE_EXT 0x24
+#define LOCAL_GLX_TRANSPARENT_RED_VALUE 0x25
+#define LOCAL_GLX_TRANSPARENT_RED_VALUE_EXT 0x25
+#define LOCAL_GLX_TRANSPARENT_RGB 0x8008
+#define LOCAL_GLX_TRANSPARENT_RGB_EXT 0x8008
+#define LOCAL_GLX_TRANSPARENT_TYPE 0x23
+#define LOCAL_GLX_TRANSPARENT_TYPE_EXT 0x23
+#define LOCAL_GLX_TRUE_COLOR 0x8002
+#define LOCAL_GLX_TRUE_COLOR_EXT 0x8002
+#define LOCAL_GLX_UNIQUE_ID_NV 0x20CE
+#define LOCAL_GLX_USE_GL 1
+#define LOCAL_GLX_VENDOR 0x1
+#define LOCAL_GLX_VENDOR_NAMES_EXT 0x20F6
+#define LOCAL_GLX_VERSION 0x2
+#define LOCAL_GLX_VIDEO_OUT_ALPHA_NV 0x20C4
+#define LOCAL_GLX_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define LOCAL_GLX_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define LOCAL_GLX_VIDEO_OUT_COLOR_NV 0x20C3
+#define LOCAL_GLX_VIDEO_OUT_DEPTH_NV 0x20C5
+#define LOCAL_GLX_VIDEO_OUT_FIELD_1_NV 0x20C9
+#define LOCAL_GLX_VIDEO_OUT_FIELD_2_NV 0x20CA
+#define LOCAL_GLX_VIDEO_OUT_FRAME_NV 0x20C8
+#define LOCAL_GLX_VIDEO_OUT_STACKED_FIELDS_1_2_NV 0x20CB
+#define LOCAL_GLX_VIDEO_OUT_STACKED_FIELDS_2_1_NV 0x20CC
+#define LOCAL_GLX_VISUAL_CAVEAT_EXT 0x20
+#define LOCAL_GLX_VISUAL_ID 0x800B
+#define LOCAL_GLX_VISUAL_ID_EXT 0x800B
+#define LOCAL_GLX_VISUAL_SELECT_GROUP_SGIX 0x8028
+#define LOCAL_GLX_WIDTH 0x801D
+#define LOCAL_GLX_WIDTH_SGIX 0x801D
+#define LOCAL_GLX_WINDOW 0x8022
+#define LOCAL_GLX_WINDOW_BIT 0x00000001
+#define LOCAL_GLX_WINDOW_BIT_SGIX 0x00000001
+#define LOCAL_GLX_WINDOW_SGIX 0x8022
+#define LOCAL_GLX_X_RENDERABLE 0x8012
+#define LOCAL_GLX_X_RENDERABLE_SGIX 0x8012
+#define LOCAL_GLX_X_VISUAL_TYPE 0x22
+#define LOCAL_GLX_X_VISUAL_TYPE_EXT 0x22
+#define LOCAL_GLX_Y_INVERTED_EXT 0x20D4
+
+// WGL
+#define LOCAL_WGL_ACCELERATION_ARB 0x2003
+#define LOCAL_WGL_ACCELERATION_EXT 0x2003
+#define LOCAL_WGL_ACCESS_READ_ONLY_NV 0x00000000
+#define LOCAL_WGL_ACCESS_READ_WRITE_NV 0x00000001
+#define LOCAL_WGL_ACCESS_WRITE_DISCARD_NV 0x00000002
+#define LOCAL_WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define LOCAL_WGL_ACCUM_ALPHA_BITS_EXT 0x2021
+#define LOCAL_WGL_ACCUM_BITS_ARB 0x201D
+#define LOCAL_WGL_ACCUM_BITS_EXT 0x201D
+#define LOCAL_WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define LOCAL_WGL_ACCUM_BLUE_BITS_EXT 0x2020
+#define LOCAL_WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define LOCAL_WGL_ACCUM_GREEN_BITS_EXT 0x201F
+#define LOCAL_WGL_ACCUM_RED_BITS_ARB 0x201E
+#define LOCAL_WGL_ACCUM_RED_BITS_EXT 0x201E
+#define LOCAL_WGL_ALPHA_BITS_ARB 0x201B
+#define LOCAL_WGL_ALPHA_BITS_EXT 0x201B
+#define LOCAL_WGL_ALPHA_SHIFT_ARB 0x201C
+#define LOCAL_WGL_ALPHA_SHIFT_EXT 0x201C
+#define LOCAL_WGL_AUX0_ARB 0x2087
+#define LOCAL_WGL_AUX1_ARB 0x2088
+#define LOCAL_WGL_AUX2_ARB 0x2089
+#define LOCAL_WGL_AUX3_ARB 0x208A
+#define LOCAL_WGL_AUX4_ARB 0x208B
+#define LOCAL_WGL_AUX5_ARB 0x208C
+#define LOCAL_WGL_AUX6_ARB 0x208D
+#define LOCAL_WGL_AUX7_ARB 0x208E
+#define LOCAL_WGL_AUX8_ARB 0x208F
+#define LOCAL_WGL_AUX9_ARB 0x2090
+#define LOCAL_WGL_AUX_BUFFERS_ARB 0x2024
+#define LOCAL_WGL_AUX_BUFFERS_EXT 0x2024
+#define LOCAL_WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
+#define LOCAL_WGL_BACK_LEFT_ARB 0x2085
+#define LOCAL_WGL_BACK_RIGHT_ARB 0x2086
+#define LOCAL_WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
+#define LOCAL_WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
+#define LOCAL_WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
+#define LOCAL_WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
+#define LOCAL_WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
+#define LOCAL_WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
+#define LOCAL_WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
+#define LOCAL_WGL_BLUE_BITS_ARB 0x2019
+#define LOCAL_WGL_BLUE_BITS_EXT 0x2019
+#define LOCAL_WGL_BLUE_SHIFT_ARB 0x201A
+#define LOCAL_WGL_BLUE_SHIFT_EXT 0x201A
+#define LOCAL_WGL_COLORSPACE_EXT 0x309D
+#define LOCAL_WGL_COLORSPACE_LINEAR_EXT 0x308A
+#define LOCAL_WGL_COLORSPACE_SRGB_EXT 0x3089
+#define LOCAL_WGL_COLOR_BITS_ARB 0x2014
+#define LOCAL_WGL_COLOR_BITS_EXT 0x2014
+#define LOCAL_WGL_COLOR_SAMPLES_NV 0x20B9
+#define LOCAL_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define LOCAL_WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define LOCAL_WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define LOCAL_WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#define LOCAL_WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define LOCAL_WGL_CONTEXT_FLAGS_ARB 0x2094
+#define LOCAL_WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define LOCAL_WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define LOCAL_WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define LOCAL_WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define LOCAL_WGL_CONTEXT_MULTIGPU_ATTRIB_AFR_NV 0x20AC
+#define LOCAL_WGL_CONTEXT_MULTIGPU_ATTRIB_MULTICAST_NV 0x20AD
+#define LOCAL_WGL_CONTEXT_MULTIGPU_ATTRIB_MULTI_DISPLAY_MULTICAST_NV 0x20AE
+#define LOCAL_WGL_CONTEXT_MULTIGPU_ATTRIB_NV 0x20AA
+#define LOCAL_WGL_CONTEXT_MULTIGPU_ATTRIB_SINGLE_NV 0x20AB
+#define LOCAL_WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
+#define LOCAL_WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define LOCAL_WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define LOCAL_WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#define LOCAL_WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define LOCAL_WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
+#define LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define LOCAL_WGL_COVERAGE_SAMPLES_NV 0x2042
+#define LOCAL_WGL_CUBE_MAP_FACE_ARB 0x207C
+#define LOCAL_WGL_DEPTH_BITS_ARB 0x2022
+#define LOCAL_WGL_DEPTH_BITS_EXT 0x2022
+#define LOCAL_WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
+#define LOCAL_WGL_DEPTH_COMPONENT_NV 0x20A7
+#define LOCAL_WGL_DEPTH_FLOAT_EXT 0x2040
+#define LOCAL_WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
+#define LOCAL_WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
+#define LOCAL_WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
+#define LOCAL_WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
+#define LOCAL_WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
+#define LOCAL_WGL_DOUBLE_BUFFER_ARB 0x2011
+#define LOCAL_WGL_DOUBLE_BUFFER_EXT 0x2011
+#define LOCAL_WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define LOCAL_WGL_DRAW_TO_BITMAP_EXT 0x2002
+#define LOCAL_WGL_DRAW_TO_PBUFFER_ARB 0x202D
+#define LOCAL_WGL_DRAW_TO_PBUFFER_EXT 0x202D
+#define LOCAL_WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define LOCAL_WGL_DRAW_TO_WINDOW_EXT 0x2001
+#define LOCAL_WGL_FLOAT_COMPONENTS_NV 0x20B0
+#define LOCAL_WGL_FONT_LINES 0
+#define LOCAL_WGL_FONT_POLYGONS 1
+#define LOCAL_WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+#define LOCAL_WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+#define LOCAL_WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
+#define LOCAL_WGL_FRONT_LEFT_ARB 0x2083
+#define LOCAL_WGL_FRONT_RIGHT_ARB 0x2084
+#define LOCAL_WGL_FULL_ACCELERATION_ARB 0x2027
+#define LOCAL_WGL_FULL_ACCELERATION_EXT 0x2027
+#define LOCAL_WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
+#define LOCAL_WGL_GAMMA_TABLE_SIZE_I3D 0x204E
+#define LOCAL_WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define LOCAL_WGL_GENERIC_ACCELERATION_EXT 0x2026
+#define LOCAL_WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
+#define LOCAL_WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
+#define LOCAL_WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
+#define LOCAL_WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
+#define LOCAL_WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
+#define LOCAL_WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
+#define LOCAL_WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
+#define LOCAL_WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
+#define LOCAL_WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
+#define LOCAL_WGL_GPU_CLOCK_AMD 0x21A4
+#define LOCAL_WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
+#define LOCAL_WGL_GPU_NUM_PIPES_AMD 0x21A5
+#define LOCAL_WGL_GPU_NUM_RB_AMD 0x21A7
+#define LOCAL_WGL_GPU_NUM_SIMD_AMD 0x21A6
+#define LOCAL_WGL_GPU_NUM_SPI_AMD 0x21A8
+#define LOCAL_WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
+#define LOCAL_WGL_GPU_RAM_AMD 0x21A3
+#define LOCAL_WGL_GPU_RENDERER_STRING_AMD 0x1F01
+#define LOCAL_WGL_GPU_VENDOR_AMD 0x1F00
+#define LOCAL_WGL_GREEN_BITS_ARB 0x2017
+#define LOCAL_WGL_GREEN_BITS_EXT 0x2017
+#define LOCAL_WGL_GREEN_SHIFT_ARB 0x2018
+#define LOCAL_WGL_GREEN_SHIFT_EXT 0x2018
+#define LOCAL_WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
+#define LOCAL_WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
+#define LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
+#define LOCAL_WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
+#define LOCAL_WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
+#define LOCAL_WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
+#define LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
+#define LOCAL_WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
+#define LOCAL_WGL_MIPMAP_LEVEL_ARB 0x207B
+#define LOCAL_WGL_MIPMAP_TEXTURE_ARB 0x2074
+#define LOCAL_WGL_NEED_PALETTE_ARB 0x2004
+#define LOCAL_WGL_NEED_PALETTE_EXT 0x2004
+#define LOCAL_WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define LOCAL_WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
+#define LOCAL_WGL_NO_ACCELERATION_ARB 0x2025
+#define LOCAL_WGL_NO_ACCELERATION_EXT 0x2025
+#define LOCAL_WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define LOCAL_WGL_NO_TEXTURE_ARB 0x2077
+#define LOCAL_WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define LOCAL_WGL_NUMBER_OVERLAYS_EXT 0x2008
+#define LOCAL_WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define LOCAL_WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
+#define LOCAL_WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define LOCAL_WGL_NUMBER_UNDERLAYS_EXT 0x2009
+#define LOCAL_WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
+#define LOCAL_WGL_NUM_VIDEO_SLOTS_NV 0x20F0
+#define LOCAL_WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
+#define LOCAL_WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
+#define LOCAL_WGL_PBUFFER_HEIGHT_ARB 0x2035
+#define LOCAL_WGL_PBUFFER_HEIGHT_EXT 0x2035
+#define LOCAL_WGL_PBUFFER_LARGEST_ARB 0x2033
+#define LOCAL_WGL_PBUFFER_LARGEST_EXT 0x2033
+#define LOCAL_WGL_PBUFFER_LOST_ARB 0x2036
+#define LOCAL_WGL_PBUFFER_WIDTH_ARB 0x2034
+#define LOCAL_WGL_PBUFFER_WIDTH_EXT 0x2034
+#define LOCAL_WGL_PIXEL_TYPE_ARB 0x2013
+#define LOCAL_WGL_PIXEL_TYPE_EXT 0x2013
+#define LOCAL_WGL_RED_BITS_ARB 0x2015
+#define LOCAL_WGL_RED_BITS_EXT 0x2015
+#define LOCAL_WGL_RED_SHIFT_ARB 0x2016
+#define LOCAL_WGL_RED_SHIFT_EXT 0x2016
+#define LOCAL_WGL_SAMPLES_3DFX 0x2061
+#define LOCAL_WGL_SAMPLES_ARB 0x2042
+#define LOCAL_WGL_SAMPLES_EXT 0x2042
+#define LOCAL_WGL_SAMPLE_BUFFERS_3DFX 0x2060
+#define LOCAL_WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define LOCAL_WGL_SAMPLE_BUFFERS_EXT 0x2041
+#define LOCAL_WGL_SHARE_ACCUM_ARB 0x200E
+#define LOCAL_WGL_SHARE_ACCUM_EXT 0x200E
+#define LOCAL_WGL_SHARE_DEPTH_ARB 0x200C
+#define LOCAL_WGL_SHARE_DEPTH_EXT 0x200C
+#define LOCAL_WGL_SHARE_STENCIL_ARB 0x200D
+#define LOCAL_WGL_SHARE_STENCIL_EXT 0x200D
+#define LOCAL_WGL_STENCIL_BITS_ARB 0x2023
+#define LOCAL_WGL_STENCIL_BITS_EXT 0x2023
+#define LOCAL_WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
+#define LOCAL_WGL_STEREO_ARB 0x2012
+#define LOCAL_WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
+#define LOCAL_WGL_STEREO_EMITTER_ENABLE_3DL 0x2055
+#define LOCAL_WGL_STEREO_EXT 0x2012
+#define LOCAL_WGL_STEREO_POLARITY_INVERT_3DL 0x2058
+#define LOCAL_WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
+#define LOCAL_WGL_SUPPORT_GDI_ARB 0x200F
+#define LOCAL_WGL_SUPPORT_GDI_EXT 0x200F
+#define LOCAL_WGL_SUPPORT_OPENGL_ARB 0x2010
+#define LOCAL_WGL_SUPPORT_OPENGL_EXT 0x2010
+#define LOCAL_WGL_SWAP_COPY_ARB 0x2029
+#define LOCAL_WGL_SWAP_COPY_EXT 0x2029
+#define LOCAL_WGL_SWAP_EXCHANGE_ARB 0x2028
+#define LOCAL_WGL_SWAP_EXCHANGE_EXT 0x2028
+#define LOCAL_WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define LOCAL_WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
+#define LOCAL_WGL_SWAP_MAIN_PLANE 0x00000001
+#define LOCAL_WGL_SWAP_METHOD_ARB 0x2007
+#define LOCAL_WGL_SWAP_METHOD_EXT 0x2007
+#define LOCAL_WGL_SWAP_OVERLAY1 0x00000002
+#define LOCAL_WGL_SWAP_OVERLAY10 0x00000400
+#define LOCAL_WGL_SWAP_OVERLAY11 0x00000800
+#define LOCAL_WGL_SWAP_OVERLAY12 0x00001000
+#define LOCAL_WGL_SWAP_OVERLAY13 0x00002000
+#define LOCAL_WGL_SWAP_OVERLAY14 0x00004000
+#define LOCAL_WGL_SWAP_OVERLAY15 0x00008000
+#define LOCAL_WGL_SWAP_OVERLAY2 0x00000004
+#define LOCAL_WGL_SWAP_OVERLAY3 0x00000008
+#define LOCAL_WGL_SWAP_OVERLAY4 0x00000010
+#define LOCAL_WGL_SWAP_OVERLAY5 0x00000020
+#define LOCAL_WGL_SWAP_OVERLAY6 0x00000040
+#define LOCAL_WGL_SWAP_OVERLAY7 0x00000080
+#define LOCAL_WGL_SWAP_OVERLAY8 0x00000100
+#define LOCAL_WGL_SWAP_OVERLAY9 0x00000200
+#define LOCAL_WGL_SWAP_UNDEFINED_ARB 0x202A
+#define LOCAL_WGL_SWAP_UNDEFINED_EXT 0x202A
+#define LOCAL_WGL_SWAP_UNDERLAY1 0x00010000
+#define LOCAL_WGL_SWAP_UNDERLAY10 0x02000000
+#define LOCAL_WGL_SWAP_UNDERLAY11 0x04000000
+#define LOCAL_WGL_SWAP_UNDERLAY12 0x08000000
+#define LOCAL_WGL_SWAP_UNDERLAY13 0x10000000
+#define LOCAL_WGL_SWAP_UNDERLAY14 0x20000000
+#define LOCAL_WGL_SWAP_UNDERLAY15 0x40000000
+#define LOCAL_WGL_SWAP_UNDERLAY2 0x00020000
+#define LOCAL_WGL_SWAP_UNDERLAY3 0x00040000
+#define LOCAL_WGL_SWAP_UNDERLAY4 0x00080000
+#define LOCAL_WGL_SWAP_UNDERLAY5 0x00100000
+#define LOCAL_WGL_SWAP_UNDERLAY6 0x00200000
+#define LOCAL_WGL_SWAP_UNDERLAY7 0x00400000
+#define LOCAL_WGL_SWAP_UNDERLAY8 0x00800000
+#define LOCAL_WGL_SWAP_UNDERLAY9 0x01000000
+#define LOCAL_WGL_TEXTURE_1D_ARB 0x2079
+#define LOCAL_WGL_TEXTURE_2D_ARB 0x207A
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_ARB 0x2078
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
+#define LOCAL_WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
+#define LOCAL_WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
+#define LOCAL_WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
+#define LOCAL_WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
+#define LOCAL_WGL_TEXTURE_FLOAT_RG_NV 0x20B6
+#define LOCAL_WGL_TEXTURE_FLOAT_R_NV 0x20B5
+#define LOCAL_WGL_TEXTURE_FORMAT_ARB 0x2072
+#define LOCAL_WGL_TEXTURE_RECTANGLE_ATI 0x21A5
+#define LOCAL_WGL_TEXTURE_RECTANGLE_NV 0x20A2
+#define LOCAL_WGL_TEXTURE_RGBA_ARB 0x2076
+#define LOCAL_WGL_TEXTURE_RGB_ARB 0x2075
+#define LOCAL_WGL_TEXTURE_TARGET_ARB 0x2073
+#define LOCAL_WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define LOCAL_WGL_TRANSPARENT_ARB 0x200A
+#define LOCAL_WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define LOCAL_WGL_TRANSPARENT_EXT 0x200A
+#define LOCAL_WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define LOCAL_WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+#define LOCAL_WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define LOCAL_WGL_TRANSPARENT_VALUE_EXT 0x200B
+#define LOCAL_WGL_TYPE_COLORINDEX_ARB 0x202C
+#define LOCAL_WGL_TYPE_COLORINDEX_EXT 0x202C
+#define LOCAL_WGL_TYPE_RGBA_ARB 0x202B
+#define LOCAL_WGL_TYPE_RGBA_EXT 0x202B
+#define LOCAL_WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
+#define LOCAL_WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
+#define LOCAL_WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
+#define LOCAL_WGL_UNIQUE_ID_NV 0x20CE
+#define LOCAL_WGL_VIDEO_OUT_ALPHA_NV 0x20C4
+#define LOCAL_WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
+#define LOCAL_WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
+#define LOCAL_WGL_VIDEO_OUT_COLOR_NV 0x20C3
+#define LOCAL_WGL_VIDEO_OUT_DEPTH_NV 0x20C5
+#define LOCAL_WGL_VIDEO_OUT_FIELD_1 0x20C9
+#define LOCAL_WGL_VIDEO_OUT_FIELD_2 0x20CA
+#define LOCAL_WGL_VIDEO_OUT_FRAME 0x20C8
+#define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
+#define LOCAL_WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
+
+#endif // GLCONSTS_H_
+
+// clang-format on
diff --git a/gfx/gl/GLConsts.py b/gfx/gl/GLConsts.py
new file mode 100755
index 0000000000..07d70c662a
--- /dev/null
+++ b/gfx/gl/GLConsts.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python3
+
+"""
+This script will regenerate and update GLConsts.h.
+
+Step 1:
+ Download the last gl.xml, egl.xml, glx.xml and wgl.xml from
+ http://www.opengl.org/registry/#specfiles into some XML_DIR:
+ wget https://www.khronos.org/registry/OpenGL/xml/gl.xml
+ wget https://www.khronos.org/registry/OpenGL/xml/glx.xml
+ wget https://www.khronos.org/registry/OpenGL/xml/wgl.xml
+ wget https://www.khronos.org/registry/EGL/api/egl.xml
+
+Step 2:
+ `py ./GLConsts.py <XML_DIR>`
+
+Step 3:
+ Do not add the downloaded XML in the patch
+
+Step 4:
+ Enjoy =)
+"""
+
+# includes
+import pathlib
+import sys
+import xml.etree.ElementTree
+from typing import List # mypy!
+
+# -
+
+(_, XML_DIR_STR) = sys.argv
+XML_DIR = pathlib.Path(XML_DIR_STR)
+
+# -
+
+HEADER = b"""
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// clang-format off
+
+#ifndef GLCONSTS_H_
+#define GLCONSTS_H_
+
+/**
+ * GENERATED FILE, DO NOT MODIFY DIRECTLY.
+ * This is a file generated directly from the official OpenGL registry
+ * xml available http://www.opengl.org/registry/#specfiles.
+ *
+ * To generate this file, see tutorial in \'GLConsts.py\'.
+ */
+"""[
+ 1:
+]
+
+FOOTER = b"""
+#endif // GLCONSTS_H_
+
+// clang-format on
+"""[
+ 1:
+]
+
+# -
+
+
+def format_lib_constant(lib, name, value):
+ # lib would be 'GL', 'EGL', 'GLX' or 'WGL'
+ # name is the name of the const (example: MAX_TEXTURE_SIZE)
+ # value is the value of the const (example: 0xABCD)
+
+ define = "#define LOCAL_" + lib + "_" + name
+ whitespace = 60 - len(define)
+ if whitespace < 0:
+ whitespace = whitespace % 8
+
+ return define + " " * whitespace + " " + value
+
+
+class GLConst:
+ def __init__(self, lib, name, value, type):
+ self.lib = lib
+ self.name = name
+ self.value = value
+ self.type = type
+
+
+class GLDatabase:
+ LIBS = ["GL", "EGL", "GLX", "WGL"]
+
+ def __init__(self):
+ self.consts = {}
+ self.libs = set(GLDatabase.LIBS)
+ self.vendors = set(["EXT", "ATI"])
+ # there is no vendor="EXT" and vendor="ATI" in gl.xml,
+ # so we manualy declare them
+
+ def load_xml(self, xml_path):
+ tree = xml.etree.ElementTree.parse(xml_path)
+ root = tree.getroot()
+
+ for enums in root.iter("enums"):
+ vendor = enums.get("vendor")
+ if not vendor:
+ # there some standart enums that do have the vendor attribute,
+ # so we fake them as ARB's enums
+ vendor = "ARB"
+
+ if vendor not in self.vendors:
+ # we map this new vendor in the vendors set.
+ self.vendors.add(vendor)
+
+ namespaceType = enums.get("type")
+
+ for enum in enums:
+ if enum.tag != "enum":
+ # this is not an enum => we skip it
+ continue
+
+ lib = enum.get("name").split("_")[0]
+
+ if lib not in self.libs:
+ # unknown library => we skip it
+ continue
+
+ name = enum.get("name")[len(lib) + 1 :]
+ value = enum.get("value")
+ type = enum.get("type")
+
+ if not type:
+ # if no type specified, we get the namespace's default type
+ type = namespaceType
+
+ self.consts[lib + "_" + name] = GLConst(lib, name, value, type)
+
+
+# -
+
+db = GLDatabase()
+db.load_xml(XML_DIR / "gl.xml")
+db.load_xml(XML_DIR / "glx.xml")
+db.load_xml(XML_DIR / "wgl.xml")
+db.load_xml(XML_DIR / "egl.xml")
+
+# -
+
+lines: List[str] = [] # noqa: E999 (bug 1573737)
+
+keys = sorted(db.consts.keys())
+
+for lib in db.LIBS:
+ lines.append("// " + lib)
+
+ for k in keys:
+ const = db.consts[k]
+
+ if const.lib != lib:
+ continue
+
+ const_str = format_lib_constant(lib, const.name, const.value)
+ lines.append(const_str)
+
+ lines.append("")
+
+# -
+
+b_lines: List[bytes] = [HEADER] + [x.encode() for x in lines] + [FOOTER]
+b_data: bytes = b"\n".join(b_lines)
+
+dest = pathlib.Path("GLConsts.h")
+dest.write_bytes(b_data)
+
+print(f"Wrote {len(b_data)} bytes.") # Some indication that we're successful.
diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp
new file mode 100644
index 0000000000..9036653af8
--- /dev/null
+++ b/gfx/gl/GLContext.cpp
@@ -0,0 +1,2652 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContext.h"
+
+#include <algorithm>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <regex>
+#include <string>
+#include <vector>
+#ifdef MOZ_WIDGET_ANDROID
+# include <sys/mman.h>
+#endif
+#if defined(XP_LINUX) && !defined(ANDROID)
+// For MesaMemoryLeakWorkaround
+# include <dlfcn.h>
+# include <link.h>
+#endif
+
+#include "GLBlitHelper.h"
+#include "GLReadTexImageHelper.h"
+#include "GLScreenBuffer.h"
+
+#include "gfxCrashReporterUtils.h"
+#include "gfxEnv.h"
+#include "gfxUtils.h"
+#include "GLContextProvider.h"
+#include "GLLibraryLoader.h"
+#include "GLTextureImage.h"
+#include "nsPrintfCString.h"
+#include "nsThreadUtils.h"
+#include "prenv.h"
+#include "prlink.h"
+#include "ScopedGLHelpers.h"
+#include "SharedSurfaceGL.h"
+#include "GfxTexturesReporter.h"
+#include "gfx2DGlue.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/StaticPrefs_gl.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/layers/BuildConstants.h"
+#include "mozilla/layers/TextureForwarder.h" // for LayersIPCChannel
+
+#include "OGLShaderProgram.h" // for ShaderProgramType
+
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Maybe.h"
+
+#ifdef XP_MACOSX
+# include <CoreServices/CoreServices.h>
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/jni/Utils.h"
+#endif
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::layers;
+
+// Zero-initialized after init().
+MOZ_THREAD_LOCAL(const GLContext*) GLContext::sCurrentContext;
+
+// If adding defines, don't forget to undefine symbols. See #undef block below.
+// clang-format off
+#define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x }} }
+#define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x, "gl" #x #y, "gl" #x #z }} }
+#define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z }} }
+#define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, {{ "gl" #x #y, "gl" #x #z, "gl" #x #w }} }
+#define END_SYMBOLS { nullptr, {} }
+// clang-format on
+
+// should match the order of GLExtensions, and be null-terminated.
+static const char* const sExtensionNames[] = {
+ "NO_EXTENSION",
+ "GL_AMD_compressed_ATC_texture",
+ "GL_ANGLE_depth_texture",
+ "GL_ANGLE_framebuffer_blit",
+ "GL_ANGLE_framebuffer_multisample",
+ "GL_ANGLE_instanced_arrays",
+ "GL_ANGLE_multiview",
+ "GL_ANGLE_provoking_vertex",
+ "GL_ANGLE_texture_compression_dxt3",
+ "GL_ANGLE_texture_compression_dxt5",
+ "GL_ANGLE_timer_query",
+ "GL_APPLE_client_storage",
+ "GL_APPLE_fence",
+ "GL_APPLE_framebuffer_multisample",
+ "GL_APPLE_sync",
+ "GL_APPLE_texture_range",
+ "GL_APPLE_vertex_array_object",
+ "GL_ARB_ES2_compatibility",
+ "GL_ARB_ES3_compatibility",
+ "GL_ARB_color_buffer_float",
+ "GL_ARB_compatibility",
+ "GL_ARB_copy_buffer",
+ "GL_ARB_depth_texture",
+ "GL_ARB_draw_buffers",
+ "GL_ARB_draw_instanced",
+ "GL_ARB_framebuffer_object",
+ "GL_ARB_framebuffer_sRGB",
+ "GL_ARB_geometry_shader4",
+ "GL_ARB_half_float_pixel",
+ "GL_ARB_instanced_arrays",
+ "GL_ARB_internalformat_query",
+ "GL_ARB_invalidate_subdata",
+ "GL_ARB_map_buffer_range",
+ "GL_ARB_occlusion_query2",
+ "GL_ARB_pixel_buffer_object",
+ "GL_ARB_provoking_vertex",
+ "GL_ARB_robust_buffer_access_behavior",
+ "GL_ARB_robustness",
+ "GL_ARB_sampler_objects",
+ "GL_ARB_seamless_cube_map",
+ "GL_ARB_shader_texture_lod",
+ "GL_ARB_sync",
+ "GL_ARB_texture_compression",
+ "GL_ARB_texture_compression_bptc",
+ "GL_ARB_texture_compression_rgtc",
+ "GL_ARB_texture_float",
+ "GL_ARB_texture_non_power_of_two",
+ "GL_ARB_texture_rectangle",
+ "GL_ARB_texture_rg",
+ "GL_ARB_texture_storage",
+ "GL_ARB_texture_swizzle",
+ "GL_ARB_timer_query",
+ "GL_ARB_transform_feedback2",
+ "GL_ARB_uniform_buffer_object",
+ "GL_ARB_vertex_array_object",
+ "GL_CHROMIUM_color_buffer_float_rgb",
+ "GL_CHROMIUM_color_buffer_float_rgba",
+ "GL_EXT_bgra",
+ "GL_EXT_blend_minmax",
+ "GL_EXT_color_buffer_float",
+ "GL_EXT_color_buffer_half_float",
+ "GL_EXT_copy_texture",
+ "GL_EXT_disjoint_timer_query",
+ "GL_EXT_draw_buffers",
+ "GL_EXT_draw_buffers2",
+ "GL_EXT_draw_instanced",
+ "GL_EXT_float_blend",
+ "GL_EXT_frag_depth",
+ "GL_EXT_framebuffer_blit",
+ "GL_EXT_framebuffer_multisample",
+ "GL_EXT_framebuffer_object",
+ "GL_EXT_framebuffer_sRGB",
+ "GL_EXT_gpu_shader4",
+ "GL_EXT_map_buffer_range",
+ "GL_EXT_multisampled_render_to_texture",
+ "GL_EXT_occlusion_query_boolean",
+ "GL_EXT_packed_depth_stencil",
+ "GL_EXT_provoking_vertex",
+ "GL_EXT_read_format_bgra",
+ "GL_EXT_robustness",
+ "GL_EXT_sRGB",
+ "GL_EXT_sRGB_write_control",
+ "GL_EXT_shader_texture_lod",
+ "GL_EXT_texture_compression_bptc",
+ "GL_EXT_texture_compression_dxt1",
+ "GL_EXT_texture_compression_rgtc",
+ "GL_EXT_texture_compression_s3tc",
+ "GL_EXT_texture_compression_s3tc_srgb",
+ "GL_EXT_texture_filter_anisotropic",
+ "GL_EXT_texture_format_BGRA8888",
+ "GL_EXT_texture_norm16",
+ "GL_EXT_texture_sRGB",
+ "GL_EXT_texture_storage",
+ "GL_EXT_timer_query",
+ "GL_EXT_transform_feedback",
+ "GL_EXT_unpack_subimage",
+ "GL_IMG_read_format",
+ "GL_IMG_texture_compression_pvrtc",
+ "GL_IMG_texture_npot",
+ "GL_KHR_debug",
+ "GL_KHR_parallel_shader_compile",
+ "GL_KHR_robust_buffer_access_behavior",
+ "GL_KHR_robustness",
+ "GL_KHR_texture_compression_astc_hdr",
+ "GL_KHR_texture_compression_astc_ldr",
+ "GL_NV_draw_instanced",
+ "GL_NV_fence",
+ "GL_NV_framebuffer_blit",
+ "GL_NV_geometry_program4",
+ "GL_NV_half_float",
+ "GL_NV_instanced_arrays",
+ "GL_NV_primitive_restart",
+ "GL_NV_texture_barrier",
+ "GL_NV_transform_feedback",
+ "GL_NV_transform_feedback2",
+ "GL_OES_EGL_image",
+ "GL_OES_EGL_image_external",
+ "GL_OES_EGL_sync",
+ "GL_OES_compressed_ETC1_RGB8_texture",
+ "GL_OES_depth24",
+ "GL_OES_depth32",
+ "GL_OES_depth_texture",
+ "GL_OES_draw_buffers_indexed",
+ "GL_OES_element_index_uint",
+ "GL_OES_fbo_render_mipmap",
+ "GL_OES_framebuffer_object",
+ "GL_OES_packed_depth_stencil",
+ "GL_OES_rgb8_rgba8",
+ "GL_OES_standard_derivatives",
+ "GL_OES_stencil8",
+ "GL_OES_texture_3D",
+ "GL_OES_texture_float",
+ "GL_OES_texture_float_linear",
+ "GL_OES_texture_half_float",
+ "GL_OES_texture_half_float_linear",
+ "GL_OES_texture_npot",
+ "GL_OES_vertex_array_object",
+ "GL_OVR_multiview2"};
+
+static bool ShouldUseTLSIsCurrent(bool useTLSIsCurrent) {
+ if (StaticPrefs::gl_use_tls_is_current() == 0) {
+ return useTLSIsCurrent;
+ }
+
+ return StaticPrefs::gl_use_tls_is_current() > 0;
+}
+
+static bool ParseVersion(const std::string& versionStr,
+ uint32_t* const out_major, uint32_t* const out_minor) {
+ static const std::regex kVersionRegex("([0-9]+)\\.([0-9]+)");
+ std::smatch match;
+ if (!std::regex_search(versionStr, match, kVersionRegex)) return false;
+
+ const auto& majorStr = match.str(1);
+ const auto& minorStr = match.str(2);
+ *out_major = atoi(majorStr.c_str());
+ *out_minor = atoi(minorStr.c_str());
+ return true;
+}
+
+/*static*/
+uint8_t GLContext::ChooseDebugFlags(const CreateContextFlags createFlags) {
+ uint8_t debugFlags = 0;
+
+#ifdef MOZ_GL_DEBUG_BUILD
+ if (gfxEnv::MOZ_GL_DEBUG()) {
+ debugFlags |= GLContext::DebugFlagEnabled;
+ }
+
+ // Enables extra verbose output, informing of the start and finish of every GL
+ // call. Useful e.g. to record information to investigate graphics system
+ // crashes/lockups
+ if (gfxEnv::MOZ_GL_DEBUG_VERBOSE()) {
+ debugFlags |= GLContext::DebugFlagTrace;
+ }
+
+ // Aborts on GL error. Can be useful to debug quicker code that is known not
+ // to generate any GL error in principle.
+ bool abortOnError = false;
+
+ if (createFlags & CreateContextFlags::NO_VALIDATION) {
+ abortOnError = true;
+
+ const auto& env = gfxEnv::MOZ_GL_DEBUG_ABORT_ON_ERROR();
+ if (env.as_str == "0") {
+ abortOnError = false;
+ }
+ }
+
+ if (abortOnError) {
+ debugFlags |= GLContext::DebugFlagAbortOnError;
+ }
+#endif
+
+ return debugFlags;
+}
+
+GLContext::GLContext(const GLContextDesc& desc, GLContext* sharedContext,
+ bool useTLSIsCurrent)
+ : mDesc(desc),
+ mUseTLSIsCurrent(ShouldUseTLSIsCurrent(useTLSIsCurrent)),
+ mDebugFlags(ChooseDebugFlags(mDesc.flags)),
+ mSharedContext(sharedContext),
+ mOwningThreadId(Some(PlatformThread::CurrentId())),
+ mWorkAroundDriverBugs(
+ StaticPrefs::gfx_work_around_driver_bugs_AtStartup()) {}
+
+GLContext::~GLContext() {
+ NS_ASSERTION(
+ IsDestroyed(),
+ "GLContext implementation must call MarkDestroyed in destructor!");
+#ifdef MOZ_GL_DEBUG_BUILD
+ if (mSharedContext) {
+ GLContext* tip = mSharedContext;
+ while (tip->mSharedContext) tip = tip->mSharedContext;
+ tip->SharedContextDestroyed(this);
+ tip->ReportOutstandingNames();
+ } else {
+ ReportOutstandingNames();
+ }
+#endif
+ // Ensure we clear sCurrentContext if we were the last context set and avoid
+ // the memory getting reused.
+ if (sCurrentContext.init() && sCurrentContext.get() == this) {
+ sCurrentContext.set(nullptr);
+ }
+}
+
+/*static*/
+void GLContext::InvalidateCurrentContext() {
+ if (sCurrentContext.init()) {
+ sCurrentContext.set(nullptr);
+ }
+}
+
+/*static*/
+void GLContext::StaticDebugCallback(GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei length,
+ const GLchar* message,
+ const GLvoid* userParam) {
+ GLContext* gl = (GLContext*)userParam;
+ gl->DebugCallback(source, type, id, severity, length, message);
+}
+
+bool GLContext::Init() {
+ MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer,
+ "GFX: GLContext::Init should only be called once.");
+
+ ScopedGfxFeatureReporter reporter("GL Context");
+
+ if (!InitImpl()) {
+ // If initialization fails, zero the symbols to avoid hard-to-understand
+ // bugs.
+ mSymbols = {};
+ NS_WARNING("GLContext::InitWithPrefix failed!");
+ return false;
+ }
+
+ reporter.SetSuccessful();
+ return true;
+}
+
+static bool LoadSymbolsWithDesc(const SymbolLoader& loader,
+ const SymLoadStruct* list, const char* desc) {
+ const auto warnOnFailure = bool(desc);
+ if (loader.LoadSymbols(list, warnOnFailure)) return true;
+
+ ClearSymbols(list);
+
+ if (desc) {
+ const nsPrintfCString err("Failed to load symbols for %s.", desc);
+ NS_ERROR(err.BeginReading());
+ }
+ return false;
+}
+
+bool GLContext::LoadExtSymbols(const SymbolLoader& loader,
+ const SymLoadStruct* list, GLExtensions ext) {
+ const char* extName = sExtensionNames[size_t(ext)];
+ if (!LoadSymbolsWithDesc(loader, list, extName)) {
+ MarkExtensionUnsupported(ext);
+ return false;
+ }
+ return true;
+};
+
+bool GLContext::LoadFeatureSymbols(const SymbolLoader& loader,
+ const SymLoadStruct* list,
+ GLFeature feature) {
+ const char* featureName = GetFeatureName(feature);
+ if (!LoadSymbolsWithDesc(loader, list, featureName)) {
+ MarkUnsupported(feature);
+ return false;
+ }
+ return true;
+};
+
+bool GLContext::InitImpl() {
+ if (!MakeCurrent(true)) return false;
+
+ const auto loader = GetSymbolLoader();
+ if (!loader) return false;
+
+ const auto fnLoadSymbols = [&](const SymLoadStruct* const list,
+ const char* const desc) {
+ return LoadSymbolsWithDesc(*loader, list, desc);
+ };
+
+ // clang-format off
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fActiveTexture, {{ "glActiveTexture", "glActiveTextureARB" }} },
+ { (PRFuncPtr*) &mSymbols.fAttachShader, {{ "glAttachShader", "glAttachShaderARB" }} },
+ { (PRFuncPtr*) &mSymbols.fBindAttribLocation, {{ "glBindAttribLocation", "glBindAttribLocationARB" }} },
+ { (PRFuncPtr*) &mSymbols.fBindBuffer, {{ "glBindBuffer", "glBindBufferARB" }} },
+ { (PRFuncPtr*) &mSymbols.fBindTexture, {{ "glBindTexture", "glBindTextureARB" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendColor, {{ "glBlendColor" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendEquation, {{ "glBlendEquation" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, {{ "glBlendEquationSeparate", "glBlendEquationSeparateEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendFunc, {{ "glBlendFunc" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, {{ "glBlendFuncSeparate", "glBlendFuncSeparateEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fBufferData, {{ "glBufferData" }} },
+ { (PRFuncPtr*) &mSymbols.fBufferSubData, {{ "glBufferSubData" }} },
+ { (PRFuncPtr*) &mSymbols.fClear, {{ "glClear" }} },
+ { (PRFuncPtr*) &mSymbols.fClearColor, {{ "glClearColor" }} },
+ { (PRFuncPtr*) &mSymbols.fClearStencil, {{ "glClearStencil" }} },
+ { (PRFuncPtr*) &mSymbols.fColorMask, {{ "glColorMask" }} },
+ { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {{ "glCompressedTexImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {{ "glCompressedTexSubImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fCullFace, {{ "glCullFace" }} },
+ { (PRFuncPtr*) &mSymbols.fDetachShader, {{ "glDetachShader", "glDetachShaderARB" }} },
+ { (PRFuncPtr*) &mSymbols.fDepthFunc, {{ "glDepthFunc" }} },
+ { (PRFuncPtr*) &mSymbols.fDepthMask, {{ "glDepthMask" }} },
+ { (PRFuncPtr*) &mSymbols.fDisable, {{ "glDisable" }} },
+ { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, {{ "glDisableVertexAttribArray", "glDisableVertexAttribArrayARB" }} },
+ { (PRFuncPtr*) &mSymbols.fDrawArrays, {{ "glDrawArrays" }} },
+ { (PRFuncPtr*) &mSymbols.fDrawElements, {{ "glDrawElements" }} },
+ { (PRFuncPtr*) &mSymbols.fEnable, {{ "glEnable" }} },
+ { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, {{ "glEnableVertexAttribArray", "glEnableVertexAttribArrayARB" }} },
+ { (PRFuncPtr*) &mSymbols.fFinish, {{ "glFinish" }} },
+ { (PRFuncPtr*) &mSymbols.fFlush, {{ "glFlush" }} },
+ { (PRFuncPtr*) &mSymbols.fFrontFace, {{ "glFrontFace" }} },
+ { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, {{ "glGetActiveAttrib", "glGetActiveAttribARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetActiveUniform, {{ "glGetActiveUniform", "glGetActiveUniformARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, {{ "glGetAttachedShaders", "glGetAttachedShadersARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetAttribLocation, {{ "glGetAttribLocation", "glGetAttribLocationARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetIntegerv, {{ "glGetIntegerv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetFloatv, {{ "glGetFloatv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetBooleanv, {{ "glGetBooleanv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, {{ "glGetBufferParameteriv", "glGetBufferParameterivARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetError, {{ "glGetError" }} },
+ { (PRFuncPtr*) &mSymbols.fGetProgramiv, {{ "glGetProgramiv", "glGetProgramivARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, {{ "glGetProgramInfoLog", "glGetProgramInfoLogARB" }} },
+ { (PRFuncPtr*) &mSymbols.fTexParameteri, {{ "glTexParameteri" }} },
+ { (PRFuncPtr*) &mSymbols.fTexParameteriv, {{ "glTexParameteriv" }} },
+ { (PRFuncPtr*) &mSymbols.fTexParameterf, {{ "glTexParameterf" }} },
+ { (PRFuncPtr*) &mSymbols.fGetString, {{ "glGetString" }} },
+ { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, {{ "glGetTexParameterfv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, {{ "glGetTexParameteriv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetUniformfv, {{ "glGetUniformfv", "glGetUniformfvARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetUniformiv, {{ "glGetUniformiv", "glGetUniformivARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetUniformLocation, {{ "glGetUniformLocation", "glGetUniformLocationARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, {{ "glGetVertexAttribfv", "glGetVertexAttribfvARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, {{ "glGetVertexAttribiv", "glGetVertexAttribivARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, {{ "glGetVertexAttribPointerv" }} },
+ { (PRFuncPtr*) &mSymbols.fHint, {{ "glHint" }} },
+ { (PRFuncPtr*) &mSymbols.fIsBuffer, {{ "glIsBuffer", "glIsBufferARB" }} },
+ { (PRFuncPtr*) &mSymbols.fIsEnabled, {{ "glIsEnabled" }} },
+ { (PRFuncPtr*) &mSymbols.fIsProgram, {{ "glIsProgram", "glIsProgramARB" }} },
+ { (PRFuncPtr*) &mSymbols.fIsShader, {{ "glIsShader", "glIsShaderARB" }} },
+ { (PRFuncPtr*) &mSymbols.fIsTexture, {{ "glIsTexture", "glIsTextureARB" }} },
+ { (PRFuncPtr*) &mSymbols.fLineWidth, {{ "glLineWidth" }} },
+ { (PRFuncPtr*) &mSymbols.fLinkProgram, {{ "glLinkProgram", "glLinkProgramARB" }} },
+ { (PRFuncPtr*) &mSymbols.fPixelStorei, {{ "glPixelStorei" }} },
+ { (PRFuncPtr*) &mSymbols.fPolygonOffset, {{ "glPolygonOffset" }} },
+ { (PRFuncPtr*) &mSymbols.fReadPixels, {{ "glReadPixels" }} },
+ { (PRFuncPtr*) &mSymbols.fSampleCoverage, {{ "glSampleCoverage" }} },
+ { (PRFuncPtr*) &mSymbols.fScissor, {{ "glScissor" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilFunc, {{ "glStencilFunc" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, {{ "glStencilFuncSeparate", "glStencilFuncSeparateEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilMask, {{ "glStencilMask" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, {{ "glStencilMaskSeparate", "glStencilMaskSeparateEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilOp, {{ "glStencilOp" }} },
+ { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, {{ "glStencilOpSeparate", "glStencilOpSeparateEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fTexImage2D, {{ "glTexImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fTexSubImage2D, {{ "glTexSubImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1f, {{ "glUniform1f" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1fv, {{ "glUniform1fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1i, {{ "glUniform1i" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1iv, {{ "glUniform1iv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2f, {{ "glUniform2f" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2fv, {{ "glUniform2fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2i, {{ "glUniform2i" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2iv, {{ "glUniform2iv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3f, {{ "glUniform3f" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3fv, {{ "glUniform3fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3i, {{ "glUniform3i" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3iv, {{ "glUniform3iv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4f, {{ "glUniform4f" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4fv, {{ "glUniform4fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4i, {{ "glUniform4i" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4iv, {{ "glUniform4iv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, {{ "glUniformMatrix2fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, {{ "glUniformMatrix3fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, {{ "glUniformMatrix4fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUseProgram, {{ "glUseProgram" }} },
+ { (PRFuncPtr*) &mSymbols.fValidateProgram, {{ "glValidateProgram" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, {{ "glVertexAttrib1f" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, {{ "glVertexAttrib2f" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, {{ "glVertexAttrib3f" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, {{ "glVertexAttrib4f" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, {{ "glVertexAttrib1fv" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, {{ "glVertexAttrib2fv" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, {{ "glVertexAttrib3fv" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, {{ "glVertexAttrib4fv" }} },
+ { (PRFuncPtr*) &mSymbols.fViewport, {{ "glViewport" }} },
+ { (PRFuncPtr*) &mSymbols.fCompileShader, {{ "glCompileShader" }} },
+ { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, {{ "glCopyTexImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, {{ "glCopyTexSubImage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fGetShaderiv, {{ "glGetShaderiv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, {{ "glGetShaderInfoLog" }} },
+ { (PRFuncPtr*) &mSymbols.fGetShaderSource, {{ "glGetShaderSource" }} },
+ { (PRFuncPtr*) &mSymbols.fShaderSource, {{ "glShaderSource" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, {{ "glVertexAttribPointer" }} },
+
+ { (PRFuncPtr*) &mSymbols.fGenBuffers, {{ "glGenBuffers", "glGenBuffersARB" }} },
+ { (PRFuncPtr*) &mSymbols.fGenTextures, {{ "glGenTextures" }} },
+ { (PRFuncPtr*) &mSymbols.fCreateProgram, {{ "glCreateProgram", "glCreateProgramARB" }} },
+ { (PRFuncPtr*) &mSymbols.fCreateShader, {{ "glCreateShader", "glCreateShaderARB" }} },
+
+ { (PRFuncPtr*) &mSymbols.fDeleteBuffers, {{ "glDeleteBuffers", "glDeleteBuffersARB" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteTextures, {{ "glDeleteTextures", "glDeleteTexturesARB" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteProgram, {{ "glDeleteProgram", "glDeleteProgramARB" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteShader, {{ "glDeleteShader", "glDeleteShaderARB" }} },
+
+ END_SYMBOLS
+ };
+ // clang-format on
+
+ if (!fnLoadSymbols(coreSymbols, "GL")) return false;
+
+ {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fGetGraphicsResetStatus,
+ {{"glGetGraphicsResetStatus", "glGetGraphicsResetStatusARB",
+ "glGetGraphicsResetStatusKHR", "glGetGraphicsResetStatusEXT"}}},
+ END_SYMBOLS};
+ (void)fnLoadSymbols(symbols, nullptr);
+
+ // We need to call the fGetError symbol directly here because if there is an
+ // unflushed reset status, we don't want to mark the context as lost. That
+ // would prevent us from recovering.
+ auto err = mSymbols.fGetError();
+ if (err == LOCAL_GL_CONTEXT_LOST) {
+ MOZ_ASSERT(mSymbols.fGetGraphicsResetStatus);
+ const auto status = fGetGraphicsResetStatus();
+ if (status) {
+ printf_stderr("Unflushed glGetGraphicsResetStatus: 0x%04x\n", status);
+ }
+ err = fGetError();
+ MOZ_ASSERT(!err);
+ }
+ if (err) {
+ MOZ_ASSERT(false);
+ return false;
+ }
+ }
+
+ ////////////////
+
+ const auto* const versionRawStr = (const char*)fGetString(LOCAL_GL_VERSION);
+ if (!versionRawStr || !*versionRawStr) {
+ // This can happen with Pernosco.
+ NS_WARNING("Empty GL version string");
+ return false;
+ }
+
+ const std::string versionStr = versionRawStr;
+ if (versionStr.find("OpenGL ES") == 0) {
+ mProfile = ContextProfile::OpenGLES;
+ }
+
+ uint32_t majorVer, minorVer;
+ if (!ParseVersion(versionStr, &majorVer, &minorVer)) {
+ MOZ_ASSERT(false, "Failed to parse GL_VERSION");
+ return false;
+ }
+ MOZ_ASSERT(majorVer < 10);
+ MOZ_ASSERT(minorVer < 10);
+ mVersion = majorVer * 100 + minorVer * 10;
+ if (mVersion < 200) return false;
+
+ ////
+
+ const auto glslVersionStr =
+ (const char*)fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION);
+ if (!glslVersionStr) {
+ // This happens on the Android emulators. We'll just return 100
+ mShadingLanguageVersion = 100;
+ } else if (ParseVersion(glslVersionStr, &majorVer, &minorVer)) {
+ MOZ_ASSERT(majorVer < 10);
+ MOZ_ASSERT(minorVer < 100);
+ mShadingLanguageVersion = majorVer * 100 + minorVer;
+ } else {
+ MOZ_ASSERT(false, "Failed to parse GL_SHADING_LANGUAGE_VERSION");
+ return false;
+ }
+
+ if (ShouldSpew()) {
+ printf_stderr("GL version detected: %u\n", mVersion);
+ printf_stderr("GLSL version detected: %u\n", mShadingLanguageVersion);
+ printf_stderr("OpenGL vendor: %s\n", fGetString(LOCAL_GL_VENDOR));
+ printf_stderr("OpenGL renderer: %s\n", fGetString(LOCAL_GL_RENDERER));
+ }
+
+ ////////////////
+
+ // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2.
+ if (mProfile == ContextProfile::OpenGLES) {
+ const SymLoadStruct symbols[] = {CORE_SYMBOL(GetShaderPrecisionFormat),
+ CORE_SYMBOL(ClearDepthf),
+ CORE_SYMBOL(DepthRangef), END_SYMBOLS};
+
+ if (!fnLoadSymbols(symbols, "OpenGL ES")) return false;
+ } else {
+ const SymLoadStruct symbols[] = {
+ CORE_SYMBOL(ClearDepth), CORE_SYMBOL(DepthRange),
+ CORE_SYMBOL(ReadBuffer), CORE_SYMBOL(MapBuffer),
+ CORE_SYMBOL(UnmapBuffer), CORE_SYMBOL(PointParameterf),
+ CORE_SYMBOL(DrawBuffer),
+ // The following functions are only used by Skia/GL in desktop mode.
+ // Other parts of Gecko should avoid using these
+ CORE_SYMBOL(DrawBuffers), CORE_SYMBOL(ClientActiveTexture),
+ CORE_SYMBOL(DisableClientState), CORE_SYMBOL(EnableClientState),
+ CORE_SYMBOL(LoadIdentity), CORE_SYMBOL(LoadMatrixf),
+ CORE_SYMBOL(MatrixMode), CORE_SYMBOL(PolygonMode), CORE_SYMBOL(TexGeni),
+ CORE_SYMBOL(TexGenf), CORE_SYMBOL(TexGenfv), CORE_SYMBOL(VertexPointer),
+ END_SYMBOLS};
+
+ if (!fnLoadSymbols(symbols, "Desktop OpenGL")) return false;
+ }
+
+ ////////////////
+
+ const char* glVendorString = (const char*)fGetString(LOCAL_GL_VENDOR);
+ const char* glRendererString = (const char*)fGetString(LOCAL_GL_RENDERER);
+ if (!glVendorString || !glRendererString) return false;
+
+ // The order of these strings must match up with the order of the enum
+ // defined in GLContext.h for vendor IDs.
+ const char* vendorMatchStrings[size_t(GLVendor::Other) + 1] = {
+ "Intel", "NVIDIA", "ATI", "Qualcomm", "Imagination",
+ "nouveau", "Vivante", "VMware, Inc.", "ARM", "Unknown"};
+
+ mVendor = GLVendor::Other;
+ for (size_t i = 0; i < size_t(GLVendor::Other); ++i) {
+ if (DoesStringMatch(glVendorString, vendorMatchStrings[i])) {
+ mVendor = GLVendor(i);
+ break;
+ }
+ }
+
+ // The order of these strings must match up with the order of the enum
+ // defined in GLContext.h for renderer IDs.
+ const char* rendererMatchStrings[size_t(GLRenderer::Other) + 1] = {
+ "Adreno 200",
+ "Adreno 205",
+ "Adreno (TM) 200",
+ "Adreno (TM) 205",
+ "Adreno (TM) 305",
+ "Adreno (TM) 320",
+ "Adreno (TM) 330",
+ "Adreno (TM) 420",
+ "Mali-400 MP",
+ "Mali-450 MP",
+ "Mali-T",
+ "PowerVR SGX 530",
+ "PowerVR SGX 540",
+ "PowerVR SGX 544MP",
+ "NVIDIA Tegra",
+ "Android Emulator",
+ "Gallium 0.4 on llvmpipe",
+ "Intel HD Graphics 3000 OpenGL Engine",
+ "Microsoft Basic Render Driver",
+ "Samsung Xclipse",
+ "Unknown"};
+
+ mRenderer = GLRenderer::Other;
+ for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) {
+ if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) {
+ mRenderer = GLRenderer(i);
+ break;
+ }
+ }
+
+ {
+ const auto versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
+ if (strstr(versionStr, "Mesa")) {
+ mIsMesa = true;
+ }
+ }
+
+ const auto Once = []() {
+ static bool did = false;
+ if (did) return false;
+ did = true;
+ return true;
+ };
+
+ bool printRenderer = ShouldSpew();
+ printRenderer |= (kIsDebug && Once());
+ if (printRenderer) {
+ printf_stderr("GL_VENDOR: %s\n", glVendorString);
+ printf_stderr("mVendor: %s\n", vendorMatchStrings[size_t(mVendor)]);
+ printf_stderr("GL_RENDERER: %s\n", glRendererString);
+ printf_stderr("mRenderer: %s\n", rendererMatchStrings[size_t(mRenderer)]);
+ printf_stderr("mIsMesa: %i\n", int(mIsMesa));
+ }
+
+ ////////////////
+
+ if (mVersion >= 300) { // Both GL3 and ES3.
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fGetStringi, {{"glGetStringi"}}}, END_SYMBOLS};
+
+ if (!fnLoadSymbols(symbols, "GetStringi")) {
+ MOZ_RELEASE_ASSERT(false, "GFX: GetStringi is required!");
+ return false;
+ }
+ }
+
+ InitExtensions();
+ if (mProfile != ContextProfile::OpenGLES) {
+ if (mVersion >= 310 && !IsExtensionSupported(ARB_compatibility)) {
+ mProfile = ContextProfile::OpenGLCore;
+ } else {
+ mProfile = ContextProfile::OpenGLCompatibility;
+ }
+ }
+ MOZ_ASSERT(mProfile != ContextProfile::Unknown);
+
+ if (ShouldSpew()) {
+ const char* profileStr = "";
+ if (mProfile == ContextProfile::OpenGLES) {
+ profileStr = " es";
+ } else if (mProfile == ContextProfile::OpenGLCore) {
+ profileStr = " core";
+ }
+ printf_stderr("Detected profile: %u%s\n", mVersion, profileStr);
+ }
+
+ InitFeatures();
+
+ ////
+
+ // Disable extensions with partial or incorrect support.
+ if (WorkAroundDriverBugs()) {
+ if (Renderer() == GLRenderer::AdrenoTM320) {
+ MarkUnsupported(GLFeature::standard_derivatives);
+ }
+
+ if (Renderer() == GLRenderer::AndroidEmulator) {
+ // Bug 1665300
+ mSymbols.fGetGraphicsResetStatus = 0;
+ }
+
+ if (Vendor() == GLVendor::Vivante) {
+ // bug 958256
+ MarkUnsupported(GLFeature::standard_derivatives);
+ }
+
+ if (Renderer() == GLRenderer::MicrosoftBasicRenderDriver) {
+ // Bug 978966: on Microsoft's "Basic Render Driver" (software renderer)
+ // multisampling hardcodes blending with the default blendfunc, which
+ // breaks WebGL.
+ MarkUnsupported(GLFeature::framebuffer_multisample);
+ }
+
+ if (IsMesa()) {
+ // DrawElementsInstanced hangs the driver.
+ MarkUnsupported(GLFeature::robust_buffer_access_behavior);
+ }
+
+ if (Renderer() == GLRenderer::SamsungXclipse) {
+ MarkUnsupported(GLFeature::invalidate_framebuffer);
+ }
+ }
+
+ if (IsExtensionSupported(GLContext::ARB_pixel_buffer_object)) {
+ MOZ_ASSERT(
+ (mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
+ "ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer"
+ " being available!");
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ const auto fnLoadForFeature = [&](const SymLoadStruct* list,
+ GLFeature feature) {
+ return this->LoadFeatureSymbols(*loader, list, feature);
+ };
+
+ // Check for ARB_framebuffer_objects
+ if (IsSupported(GLFeature::framebuffer_object)) {
+ // https://www.opengl.org/registry/specs/ARB/framebuffer_object.txt
+ const SymLoadStruct symbols[] = {
+ CORE_SYMBOL(IsRenderbuffer),
+ CORE_SYMBOL(BindRenderbuffer),
+ CORE_SYMBOL(DeleteRenderbuffers),
+ CORE_SYMBOL(GenRenderbuffers),
+ CORE_SYMBOL(RenderbufferStorage),
+ CORE_SYMBOL(RenderbufferStorageMultisample),
+ CORE_SYMBOL(GetRenderbufferParameteriv),
+ CORE_SYMBOL(IsFramebuffer),
+ CORE_SYMBOL(BindFramebuffer),
+ CORE_SYMBOL(DeleteFramebuffers),
+ CORE_SYMBOL(GenFramebuffers),
+ CORE_SYMBOL(CheckFramebufferStatus),
+ CORE_SYMBOL(FramebufferTexture2D),
+ CORE_SYMBOL(FramebufferTextureLayer),
+ CORE_SYMBOL(FramebufferRenderbuffer),
+ CORE_SYMBOL(GetFramebufferAttachmentParameteriv),
+ CORE_SYMBOL(BlitFramebuffer),
+ CORE_SYMBOL(GenerateMipmap),
+ END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::framebuffer_object);
+ }
+
+ if (!IsSupported(GLFeature::framebuffer_object)) {
+ // Check for aux symbols based on extensions
+ if (IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
+ const SymLoadStruct symbols[] = {
+ CORE_EXT_SYMBOL2(IsRenderbuffer, EXT, OES),
+ CORE_EXT_SYMBOL2(BindRenderbuffer, EXT, OES),
+ CORE_EXT_SYMBOL2(DeleteRenderbuffers, EXT, OES),
+ CORE_EXT_SYMBOL2(GenRenderbuffers, EXT, OES),
+ CORE_EXT_SYMBOL2(RenderbufferStorage, EXT, OES),
+ CORE_EXT_SYMBOL2(GetRenderbufferParameteriv, EXT, OES),
+ CORE_EXT_SYMBOL2(IsFramebuffer, EXT, OES),
+ CORE_EXT_SYMBOL2(BindFramebuffer, EXT, OES),
+ CORE_EXT_SYMBOL2(DeleteFramebuffers, EXT, OES),
+ CORE_EXT_SYMBOL2(GenFramebuffers, EXT, OES),
+ CORE_EXT_SYMBOL2(CheckFramebufferStatus, EXT, OES),
+ CORE_EXT_SYMBOL2(FramebufferTexture2D, EXT, OES),
+ CORE_EXT_SYMBOL2(FramebufferRenderbuffer, EXT, OES),
+ CORE_EXT_SYMBOL2(GetFramebufferAttachmentParameteriv, EXT, OES),
+ CORE_EXT_SYMBOL2(GenerateMipmap, EXT, OES),
+ END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::framebuffer_object_EXT_OES);
+ }
+
+ if (IsSupported(GLFeature::framebuffer_blit)) {
+ const SymLoadStruct symbols[] = {
+ EXT_SYMBOL3(BlitFramebuffer, ANGLE, EXT, NV), END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::framebuffer_blit);
+ }
+
+ if (IsSupported(GLFeature::framebuffer_multisample)) {
+ const SymLoadStruct symbols[] = {
+ EXT_SYMBOL3(RenderbufferStorageMultisample, ANGLE, APPLE, EXT),
+ END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::framebuffer_multisample);
+ }
+
+ if (IsExtensionSupported(GLContext::ARB_geometry_shader4) ||
+ IsExtensionSupported(GLContext::NV_geometry_program4)) {
+ const SymLoadStruct symbols[] = {
+ EXT_SYMBOL2(FramebufferTextureLayer, ARB, EXT), END_SYMBOLS};
+ if (!fnLoadSymbols(symbols,
+ "ARB_geometry_shader4/NV_geometry_program4")) {
+ MarkExtensionUnsupported(GLContext::ARB_geometry_shader4);
+ MarkExtensionUnsupported(GLContext::NV_geometry_program4);
+ }
+ }
+ }
+
+ if (!IsSupported(GLFeature::framebuffer_object) &&
+ !IsSupported(GLFeature::framebuffer_object_EXT_OES)) {
+ NS_ERROR("GLContext requires support for framebuffer objects.");
+ return false;
+ }
+ MOZ_RELEASE_ASSERT(mSymbols.fBindFramebuffer,
+ "GFX: mSymbols.fBindFramebuffer zero or not set.");
+
+ ////////////////
+
+ const auto err = fGetError();
+ MOZ_RELEASE_ASSERT(!IsBadCallError(err));
+ if (err) return false;
+
+ LoadMoreSymbols(*loader);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ raw_fGetIntegerv(LOCAL_GL_VIEWPORT, mViewportRect);
+ raw_fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mScissorRect);
+ raw_fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+ raw_fGetIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &mMaxCubeMapTextureSize);
+ raw_fGetIntegerv(LOCAL_GL_MAX_RENDERBUFFER_SIZE, &mMaxRenderbufferSize);
+ raw_fGetIntegerv(LOCAL_GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
+
+ if (mWorkAroundDriverBugs) {
+ int maxTexSize = INT32_MAX;
+ int maxCubeSize = INT32_MAX;
+#ifdef XP_MACOSX
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1544446
+ // Mojave exposes 16k textures, but gives FRAMEBUFFER_UNSUPPORTED for any
+ // 16k*16k FB except rgba8 without depth/stencil.
+ // The max supported sizes changes based on involved formats.
+ // (RGBA32F more restrictive than RGBA16F)
+ maxTexSize = 8192;
+#endif
+#ifdef MOZ_X11
+ if (mVendor == GLVendor::Nouveau) {
+ // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau.
+ maxCubeSize = 2048;
+ } else if (mVendor == GLVendor::Intel) {
+ // Bug 1199923. Driver seems to report a larger max size than
+ // actually supported.
+ maxTexSize = mMaxTextureSize / 2;
+ }
+ // Bug 1367570. Explicitly set vertex attributes [1,3] to opaque
+ // black because Nvidia doesn't do it for us.
+ if (mVendor == GLVendor::NVIDIA) {
+ for (size_t i = 1; i <= 3; ++i) {
+ mSymbols.fVertexAttrib4f(i, 0, 0, 0, 1);
+ }
+ }
+#endif
+ if (Renderer() == GLRenderer::AdrenoTM420) {
+ // see bug 1194923. Calling glFlush before glDeleteFramebuffers
+ // prevents occasional driver crash.
+ mNeedsFlushBeforeDeleteFB = true;
+ }
+
+ // -
+
+ const auto fnLimit = [&](int* const driver, const int limit) {
+ if (*driver > limit) {
+ *driver = limit;
+ mNeedsTextureSizeChecks = true;
+ }
+ };
+
+ fnLimit(&mMaxTextureSize, maxTexSize);
+ fnLimit(&mMaxRenderbufferSize, maxTexSize);
+
+ maxCubeSize = std::min(maxCubeSize, maxTexSize);
+ fnLimit(&mMaxCubeMapTextureSize, maxCubeSize);
+ }
+
+ if (IsSupported(GLFeature::framebuffer_multisample)) {
+ fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples);
+ }
+
+ mMaxTexOrRbSize = std::min(mMaxTextureSize, mMaxRenderbufferSize);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ // We're ready for final setup.
+ fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
+ MOZ_GL_ASSERT(this, IsCurrent());
+
+ if (ShouldSpew() && IsExtensionSupported(KHR_debug)) {
+ fEnable(LOCAL_GL_DEBUG_OUTPUT);
+ fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ fDebugMessageCallback(&StaticDebugCallback, (void*)this);
+ fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
+ LOCAL_GL_DONT_CARE, 0, nullptr, true);
+ }
+
+ return true;
+}
+
+void GLContext::LoadMoreSymbols(const SymbolLoader& loader) {
+ const auto fnLoadForExt = [&](const SymLoadStruct* list, GLExtensions ext) {
+ return this->LoadExtSymbols(loader, list, ext);
+ };
+
+ const auto fnLoadForFeature = [&](const SymLoadStruct* list,
+ GLFeature feature) {
+ return this->LoadFeatureSymbols(loader, list, feature);
+ };
+
+ const auto fnLoadFeatureByCore = [&](const SymLoadStruct* coreList,
+ const SymLoadStruct* extList,
+ GLFeature feature) {
+ const bool useCore = this->IsFeatureProvidedByCoreSymbols(feature);
+ const auto list = useCore ? coreList : extList;
+ return fnLoadForFeature(list, feature);
+ };
+
+ if (IsSupported(GLFeature::robustness)) {
+ const auto resetStrategy =
+ GetIntAs<GLuint>(LOCAL_GL_RESET_NOTIFICATION_STRATEGY);
+ if (resetStrategy != LOCAL_GL_LOSE_CONTEXT_ON_RESET) {
+ NS_WARNING(
+ "Robustness supported, strategy is not LOSE_CONTEXT_ON_RESET!");
+ if (ShouldSpew()) {
+ const bool isDisabled =
+ (resetStrategy == LOCAL_GL_NO_RESET_NOTIFICATION);
+ printf_stderr("Strategy: %s (0x%04x)",
+ (isDisabled ? "disabled" : "unrecognized"),
+ resetStrategy);
+ }
+ MarkUnsupported(GLFeature::robustness);
+ }
+ }
+
+ if (IsSupported(GLFeature::sync)) {
+ const SymLoadStruct symbols[] = {
+ CORE_SYMBOL(FenceSync), CORE_SYMBOL(IsSync),
+ CORE_SYMBOL(DeleteSync), CORE_SYMBOL(ClientWaitSync),
+ CORE_SYMBOL(WaitSync), CORE_SYMBOL(GetInteger64v),
+ CORE_SYMBOL(GetSynciv), END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::sync);
+ }
+
+ if (IsExtensionSupported(OES_EGL_image)) {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fEGLImageTargetTexture2D,
+ {{"glEGLImageTargetTexture2DOES"}}},
+ {(PRFuncPtr*)&mSymbols.fEGLImageTargetRenderbufferStorage,
+ {{"glEGLImageTargetRenderbufferStorageOES"}}},
+ END_SYMBOLS};
+ fnLoadForExt(symbols, OES_EGL_image);
+ }
+
+ if (IsExtensionSupported(APPLE_texture_range)) {
+ const SymLoadStruct symbols[] = {CORE_SYMBOL(TextureRangeAPPLE),
+ END_SYMBOLS};
+ fnLoadForExt(symbols, APPLE_texture_range);
+ }
+
+ if (IsExtensionSupported(APPLE_fence)) {
+ const SymLoadStruct symbols[] = {CORE_SYMBOL(FinishObjectAPPLE),
+ CORE_SYMBOL(TestObjectAPPLE), END_SYMBOLS};
+ fnLoadForExt(symbols, APPLE_fence);
+ }
+
+ // clang-format off
+
+ if (IsSupported(GLFeature::vertex_array_object)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArray" }} },
+ { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArrays" }} },
+ { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArray" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArrays" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fIsVertexArray, {{ "glIsVertexArrayARB", "glIsVertexArrayOES", "glIsVertexArrayAPPLE" }} },
+ { (PRFuncPtr*) &mSymbols.fGenVertexArrays, {{ "glGenVertexArraysARB", "glGenVertexArraysOES", "glGenVertexArraysAPPLE" }} },
+ { (PRFuncPtr*) &mSymbols.fBindVertexArray, {{ "glBindVertexArrayARB", "glBindVertexArrayOES", "glBindVertexArrayAPPLE" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, {{ "glDeleteVertexArraysARB", "glDeleteVertexArraysOES", "glDeleteVertexArraysAPPLE" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object);
+ }
+
+ if (IsSupported(GLFeature::draw_instanced)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstanced" }} },
+ { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstanced" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, {{ "glDrawArraysInstancedARB", "glDrawArraysInstancedEXT", "glDrawArraysInstancedNV", "glDrawArraysInstancedANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, {{ "glDrawElementsInstancedARB", "glDrawElementsInstancedEXT", "glDrawElementsInstancedNV", "glDrawElementsInstancedANGLE" }}
+ },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced);
+ }
+
+ if (IsSupported(GLFeature::instanced_arrays)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisor" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, {{ "glVertexAttribDivisorARB", "glVertexAttribDivisorNV", "glVertexAttribDivisorANGLE" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays);
+ }
+
+ if (IsSupported(GLFeature::texture_storage)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2D" }} },
+ { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3D" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fTexStorage2D, {{ "glTexStorage2DEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fTexStorage3D, {{ "glTexStorage3DEXT" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage);
+ }
+
+ if (IsSupported(GLFeature::sampler_objects)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGenSamplers, {{ "glGenSamplers" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteSamplers, {{ "glDeleteSamplers" }} },
+ { (PRFuncPtr*) &mSymbols.fIsSampler, {{ "glIsSampler" }} },
+ { (PRFuncPtr*) &mSymbols.fBindSampler, {{ "glBindSampler" }} },
+ { (PRFuncPtr*) &mSymbols.fSamplerParameteri, {{ "glSamplerParameteri" }} },
+ { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, {{ "glSamplerParameteriv" }} },
+ { (PRFuncPtr*) &mSymbols.fSamplerParameterf, {{ "glSamplerParameterf" }} },
+ { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, {{ "glSamplerParameterfv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, {{ "glGetSamplerParameteriv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, {{ "glGetSamplerParameterfv" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::sampler_objects);
+ }
+
+ // ARB_transform_feedback2/NV_transform_feedback2 is a
+ // superset of EXT_transform_feedback/NV_transform_feedback
+ // and adds glPauseTransformFeedback &
+ // glResumeTransformFeedback, which are required for WebGL2.
+ if (IsSupported(GLFeature::transform_feedback2)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBase" }} },
+ { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRange" }} },
+ { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacks" }} },
+ { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedback" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacks" }} },
+ { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedback" }} },
+ { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedback" }} },
+ { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedback" }} },
+ { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryings" }} },
+ { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVarying" }} },
+ { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedback" }} },
+ { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedback" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBindBufferBase, {{ "glBindBufferBaseEXT", "glBindBufferBaseNV" }} },
+ { (PRFuncPtr*) &mSymbols.fBindBufferRange, {{ "glBindBufferRangeEXT", "glBindBufferRangeNV" }} },
+ { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, {{ "glGenTransformFeedbacksNV" }} },
+ { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, {{ "glBindTransformFeedbackNV" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, {{ "glDeleteTransformFeedbacksNV" }} },
+ { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, {{ "glIsTransformFeedbackNV" }} },
+ { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, {{ "glBeginTransformFeedbackEXT", "glBeginTransformFeedbackNV" }} },
+ { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, {{ "glEndTransformFeedbackEXT", "glEndTransformFeedbackNV" }} },
+ { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, {{ "glTransformFeedbackVaryingsEXT", "glTransformFeedbackVaryingsNV" }} },
+ { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, {{ "glGetTransformFeedbackVaryingEXT", "glGetTransformFeedbackVaryingNV" }} },
+ { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, {{ "glPauseTransformFeedbackNV" }} },
+ { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, {{ "glResumeTransformFeedbackNV" }} },
+ END_SYMBOLS
+ };
+ if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::transform_feedback2)) {
+ // Also mark bind_buffer_offset as unsupported.
+ MarkUnsupported(GLFeature::bind_buffer_offset);
+ }
+ }
+
+ if (IsSupported(GLFeature::bind_buffer_offset)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBindBufferOffset, {{ "glBindBufferOffset" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBindBufferOffset,
+ {{ "glBindBufferOffsetEXT", "glBindBufferOffsetNV" }}
+ },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset);
+ }
+
+ if (IsSupported(GLFeature::query_counter)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounter" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fQueryCounter, {{ "glQueryCounterEXT", "glQueryCounterANGLE" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter);
+ }
+
+ if (IsSupported(GLFeature::query_objects)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQuery" }} },
+ { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueries" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueries" }} },
+ { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQuery" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryiv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuiv" }} },
+ { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQuery" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBeginQuery, {{ "glBeginQueryEXT", "glBeginQueryANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fGenQueries, {{ "glGenQueriesEXT", "glGenQueriesANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteQueries, {{ "glDeleteQueriesEXT", "glDeleteQueriesANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fEndQuery, {{ "glEndQueryEXT", "glEndQueryANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryiv, {{ "glGetQueryivEXT", "glGetQueryivANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, {{ "glGetQueryObjectuivEXT", "glGetQueryObjectuivANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fIsQuery, {{ "glIsQueryEXT", "glIsQueryANGLE" }} },
+ END_SYMBOLS
+ };
+ if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_objects)) {
+ MarkUnsupported(GLFeature::get_query_object_i64v);
+ MarkUnsupported(GLFeature::get_query_object_iv);
+ MarkUnsupported(GLFeature::occlusion_query);
+ MarkUnsupported(GLFeature::occlusion_query_boolean);
+ MarkUnsupported(GLFeature::occlusion_query2);
+ }
+ }
+
+ if (IsSupported(GLFeature::get_query_object_i64v)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64v" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64v" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, {{ "glGetQueryObjecti64vEXT", "glGetQueryObjecti64vANGLE" }} },
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, {{ "glGetQueryObjectui64vEXT", "glGetQueryObjectui64vANGLE" }} },
+ END_SYMBOLS
+ };
+ if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_i64v)) {
+ MarkUnsupported(GLFeature::query_counter);
+ }
+ }
+
+ if (IsSupported(GLFeature::get_query_object_iv)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectiv" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, {{ "glGetQueryObjectivEXT", "glGetQueryObjectivANGLE" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv);
+ }
+
+ if (IsSupported(GLFeature::clear_buffers)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fClearBufferfi, {{ "glClearBufferfi", }} },
+ { (PRFuncPtr*) &mSymbols.fClearBufferfv, {{ "glClearBufferfv", }} },
+ { (PRFuncPtr*) &mSymbols.fClearBufferiv, {{ "glClearBufferiv", }} },
+ { (PRFuncPtr*) &mSymbols.fClearBufferuiv, {{ "glClearBufferuiv" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::clear_buffers);
+ }
+
+ if (IsSupported(GLFeature::copy_buffer)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, {{ "glCopyBufferSubData" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::copy_buffer);
+ }
+
+ if (IsSupported(GLFeature::draw_buffers)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffers" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fDrawBuffers, {{ "glDrawBuffersARB", "glDrawBuffersEXT" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers);
+ }
+
+ if (IsSupported(GLFeature::draw_buffers_indexed)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparatei" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparatei" }} },
+ { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaski" }} },
+ { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisablei" }} },
+ { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnablei" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fBlendEquationSeparatei, {{ "glBlendEquationSeparateiOES" }} },
+ { (PRFuncPtr*) &mSymbols.fBlendFuncSeparatei, {{ "glBlendFuncSeparateiOES" }} },
+ { (PRFuncPtr*) &mSymbols.fColorMaski, {{ "glColorMaskiOES" }} },
+ { (PRFuncPtr*) &mSymbols.fDisablei, {{ "glDisableiOES" }} },
+ { (PRFuncPtr*) &mSymbols.fEnablei, {{ "glEnableiOES" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers_indexed);
+ }
+
+ if (IsSupported(GLFeature::get_integer_indexed)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegeri_v" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] ={
+ { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, {{ "glGetIntegerIndexedvEXT" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed);
+ }
+
+ if (IsSupported(GLFeature::get_integer64_indexed)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, {{ "glGetInteger64i_v" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::get_integer64_indexed);
+ }
+
+ if (IsSupported(GLFeature::gpu_shader4)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, {{ "glGetVertexAttribIiv", "glGetVertexAttribIivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, {{ "glGetVertexAttribIuiv", "glGetVertexAttribIuivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, {{ "glVertexAttribI4i", "glVertexAttribI4iEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, {{ "glVertexAttribI4iv", "glVertexAttribI4ivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, {{ "glVertexAttribI4ui", "glVertexAttribI4uiEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, {{ "glVertexAttribI4uiv", "glVertexAttribI4uivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, {{ "glVertexAttribIPointer", "glVertexAttribIPointerEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1ui, {{ "glUniform1ui", "glUniform1uiEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2ui, {{ "glUniform2ui", "glUniform2uiEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3ui, {{ "glUniform3ui", "glUniform3uiEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4ui, {{ "glUniform4ui", "glUniform4uiEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform1uiv, {{ "glUniform1uiv", "glUniform1uivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform2uiv, {{ "glUniform2uiv", "glUniform2uivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform3uiv, {{ "glUniform3uiv", "glUniform3uivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fUniform4uiv, {{ "glUniform4uiv", "glUniform4uivEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, {{ "glGetFragDataLocation", "glGetFragDataLocationEXT" }} },
+ { (PRFuncPtr*) &mSymbols.fGetUniformuiv, {{ "glGetUniformuiv", "glGetUniformuivEXT" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::gpu_shader4);
+ }
+
+ if (IsSupported(GLFeature::map_buffer_range)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fMapBufferRange, {{ "glMapBufferRange" }} },
+ { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, {{ "glFlushMappedBufferRange" }} },
+ { (PRFuncPtr*) &mSymbols.fUnmapBuffer, {{ "glUnmapBuffer" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::map_buffer_range);
+ }
+
+ if (IsSupported(GLFeature::texture_3D)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3D" }} },
+ { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3D" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fTexImage3D, {{ "glTexImage3DOES" }} },
+ { (PRFuncPtr*) &mSymbols.fTexSubImage3D, {{ "glTexSubImage3DOES" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D);
+ }
+
+ if (IsSupported(GLFeature::texture_3D_compressed)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3D" }} },
+ { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3D" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, {{ "glCompressedTexImage3DARB", "glCompressedTexImage3DOES" }} },
+ { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, {{ "glCompressedTexSubImage3DARB", "glCompressedTexSubImage3DOES" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed);
+ }
+
+ if (IsSupported(GLFeature::texture_3D_copy)) {
+ const SymLoadStruct coreSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3D" }} },
+ END_SYMBOLS
+ };
+ const SymLoadStruct extSymbols[] = {
+ { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, {{ "glCopyTexSubImage3DEXT", "glCopyTexSubImage3DOES" }} },
+ END_SYMBOLS
+ };
+ fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_copy);
+ }
+
+ if (IsSupported(GLFeature::uniform_buffer_object)) {
+ // Note: Don't query for glGetActiveUniformName because it is not
+ // supported by GL ES 3.
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGetUniformIndices, {{ "glGetUniformIndices" }} },
+ { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, {{ "glGetActiveUniformsiv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, {{ "glGetUniformBlockIndex" }} },
+ { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, {{ "glGetActiveUniformBlockiv" }} },
+ { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, {{ "glGetActiveUniformBlockName" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, {{ "glUniformBlockBinding" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::uniform_buffer_object);
+ }
+
+ if (IsSupported(GLFeature::uniform_matrix_nonsquare)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, {{ "glUniformMatrix2x3fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, {{ "glUniformMatrix2x4fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, {{ "glUniformMatrix3x2fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, {{ "glUniformMatrix3x4fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, {{ "glUniformMatrix4x2fv" }} },
+ { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, {{ "glUniformMatrix4x3fv" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::uniform_matrix_nonsquare);
+ }
+
+ if (IsSupported(GLFeature::internalformat_query)) {
+ const SymLoadStruct symbols[] = {
+ CORE_SYMBOL(GetInternalformativ),
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::internalformat_query);
+ }
+
+ if (IsSupported(GLFeature::invalidate_framebuffer)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fInvalidateFramebuffer, {{ "glInvalidateFramebuffer" }} },
+ { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, {{ "glInvalidateSubFramebuffer" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer);
+ }
+
+ if (IsSupported(GLFeature::multiview)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fFramebufferTextureMultiview, {{
+ "glFramebufferTextureMultiviewOVR",
+ "glFramebufferTextureMultiviewLayeredANGLE"
+ }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::multiview);
+ }
+
+ if (IsSupported(GLFeature::prim_restart)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, {{ "glPrimitiveRestartIndex", "glPrimitiveRestartIndexNV" }} },
+ END_SYMBOLS
+ };
+ fnLoadForFeature(symbols, GLFeature::prim_restart);
+ }
+
+ if (IsExtensionSupported(KHR_debug)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fDebugMessageControl, {{ "glDebugMessageControl", "glDebugMessageControlKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, {{ "glDebugMessageInsert", "glDebugMessageInsertKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, {{ "glDebugMessageCallback", "glDebugMessageCallbackKHR" }} },
+ { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, {{ "glGetDebugMessageLog", "glGetDebugMessageLogKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fGetPointerv, {{ "glGetPointerv", "glGetPointervKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fPushDebugGroup, {{ "glPushDebugGroup", "glPushDebugGroupKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fPopDebugGroup, {{ "glPopDebugGroup", "glPopDebugGroupKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fObjectLabel, {{ "glObjectLabel", "glObjectLabelKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fGetObjectLabel, {{ "glGetObjectLabel", "glGetObjectLabelKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, {{ "glObjectPtrLabel", "glObjectPtrLabelKHR", }} },
+ { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, {{ "glGetObjectPtrLabel", "glGetObjectPtrLabelKHR", }} },
+ END_SYMBOLS
+ };
+ fnLoadForExt(symbols, KHR_debug);
+ }
+
+ if (IsExtensionSupported(NV_fence)) {
+ const SymLoadStruct symbols[] = {
+ { (PRFuncPtr*) &mSymbols.fGenFences, {{ "glGenFencesNV" }} },
+ { (PRFuncPtr*) &mSymbols.fDeleteFences, {{ "glDeleteFencesNV" }} },
+ { (PRFuncPtr*) &mSymbols.fSetFence, {{ "glSetFenceNV" }} },
+ { (PRFuncPtr*) &mSymbols.fTestFence, {{ "glTestFenceNV" }} },
+ { (PRFuncPtr*) &mSymbols.fFinishFence, {{ "glFinishFenceNV" }} },
+ { (PRFuncPtr*) &mSymbols.fIsFence, {{ "glIsFenceNV" }} },
+ { (PRFuncPtr*) &mSymbols.fGetFenceiv, {{ "glGetFenceivNV" }} },
+ END_SYMBOLS
+ };
+ fnLoadForExt(symbols, NV_fence);
+ }
+
+ // clang-format on
+
+ if (IsExtensionSupported(NV_texture_barrier)) {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fTextureBarrier, {{"glTextureBarrierNV"}}},
+ END_SYMBOLS};
+ fnLoadForExt(symbols, NV_texture_barrier);
+ }
+
+ if (IsSupported(GLFeature::read_buffer)) {
+ const SymLoadStruct symbols[] = {CORE_SYMBOL(ReadBuffer), END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::read_buffer);
+ }
+
+ if (IsExtensionSupported(APPLE_framebuffer_multisample)) {
+ const SymLoadStruct symbols[] = {
+ CORE_SYMBOL(ResolveMultisampleFramebufferAPPLE), END_SYMBOLS};
+ fnLoadForExt(symbols, APPLE_framebuffer_multisample);
+ }
+
+ if (IsSupported(GLFeature::provoking_vertex)) {
+ const SymLoadStruct symbols[] = {{(PRFuncPtr*)&mSymbols.fProvokingVertex,
+ {{
+ "glProvokingVertex",
+ "glProvokingVertexANGLE",
+ "glProvokingVertexEXT",
+ }}},
+ END_SYMBOLS};
+ fnLoadForFeature(symbols, GLFeature::provoking_vertex);
+ }
+
+ // Load developer symbols, don't fail if we can't find them.
+ const SymLoadStruct devSymbols[] = {CORE_SYMBOL(GetTexImage),
+ CORE_SYMBOL(GetTexLevelParameteriv),
+ END_SYMBOLS};
+ const bool warnOnFailures = ShouldSpew();
+ (void)loader.LoadSymbols(devSymbols, warnOnFailures);
+}
+
+#undef CORE_SYMBOL
+#undef CORE_EXT_SYMBOL2
+#undef EXT_SYMBOL2
+#undef EXT_SYMBOL3
+#undef END_SYMBOLS
+
+void GLContext::DebugCallback(GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei length,
+ const GLchar* message) {
+ nsAutoCString sourceStr;
+ switch (source) {
+ case LOCAL_GL_DEBUG_SOURCE_API:
+ sourceStr = "SOURCE_API"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ sourceStr = "SOURCE_WINDOW_SYSTEM"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER:
+ sourceStr = "SOURCE_SHADER_COMPILER"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY:
+ sourceStr = "SOURCE_THIRD_PARTY"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_APPLICATION:
+ sourceStr = "SOURCE_APPLICATION"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SOURCE_OTHER:
+ sourceStr = "SOURCE_OTHER"_ns;
+ break;
+ default:
+ sourceStr = nsPrintfCString("<source 0x%04x>", source);
+ break;
+ }
+
+ nsAutoCString typeStr;
+ switch (type) {
+ case LOCAL_GL_DEBUG_TYPE_ERROR:
+ typeStr = "TYPE_ERROR"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ typeStr = "TYPE_DEPRECATED_BEHAVIOR"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ typeStr = "TYPE_UNDEFINED_BEHAVIOR"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_PORTABILITY:
+ typeStr = "TYPE_PORTABILITY"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_PERFORMANCE:
+ typeStr = "TYPE_PERFORMANCE"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_OTHER:
+ typeStr = "TYPE_OTHER"_ns;
+ break;
+ case LOCAL_GL_DEBUG_TYPE_MARKER:
+ typeStr = "TYPE_MARKER"_ns;
+ break;
+ default:
+ typeStr = nsPrintfCString("<type 0x%04x>", type);
+ break;
+ }
+
+ nsAutoCString sevStr;
+ switch (severity) {
+ case LOCAL_GL_DEBUG_SEVERITY_HIGH:
+ sevStr = "SEVERITY_HIGH"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_MEDIUM:
+ sevStr = "SEVERITY_MEDIUM"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_LOW:
+ sevStr = "SEVERITY_LOW"_ns;
+ break;
+ case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION:
+ sevStr = "SEVERITY_NOTIFICATION"_ns;
+ break;
+ default:
+ sevStr = nsPrintfCString("<severity 0x%04x>", severity);
+ break;
+ }
+
+ printf_stderr("[KHR_debug: 0x%" PRIxPTR "] ID %u: %s, %s, %s:\n %s\n",
+ (uintptr_t)this, id, sourceStr.BeginReading(),
+ typeStr.BeginReading(), sevStr.BeginReading(), message);
+}
+
+void GLContext::InitExtensions() {
+ MOZ_GL_ASSERT(this, IsCurrent());
+
+ std::vector<nsCString> driverExtensionList;
+
+ [&]() {
+ if (mSymbols.fGetStringi) {
+ GLuint count = 0;
+ if (GetPotentialInteger(LOCAL_GL_NUM_EXTENSIONS, (GLint*)&count)) {
+ for (GLuint i = 0; i < count; i++) {
+ // This is UTF-8.
+ const char* rawExt = (const char*)fGetStringi(LOCAL_GL_EXTENSIONS, i);
+
+ // We CANNOT use nsDependentCString here, because the spec doesn't
+ // guarantee that the pointers returned are different, only that their
+ // contents are. On Flame, each of these index string queries returns
+ // the same address.
+ driverExtensionList.push_back(nsCString(rawExt));
+ }
+ return;
+ }
+ }
+
+ const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS);
+ if (rawExts) {
+ nsDependentCString exts(rawExts);
+ SplitByChar(exts, ' ', &driverExtensionList);
+ }
+ }();
+ const auto err = fGetError();
+ MOZ_ALWAYS_TRUE(!IsBadCallError(err));
+
+ const bool shouldDumpExts = ShouldDumpExts();
+ if (shouldDumpExts) {
+ printf_stderr("%i GL driver extensions: (*: recognized)\n",
+ (uint32_t)driverExtensionList.size());
+ }
+
+ MarkBitfieldByStrings(driverExtensionList, shouldDumpExts, sExtensionNames,
+ &mAvailableExtensions);
+
+ if (WorkAroundDriverBugs()) {
+ if (Vendor() == GLVendor::Qualcomm) {
+ // Some Adreno drivers do not report GL_OES_EGL_sync, but they really do
+ // support it.
+ MarkExtensionSupported(OES_EGL_sync);
+ }
+
+ if (Vendor() == GLVendor::ATI) {
+ // ATI drivers say this extension exists, but we can't
+ // actually find the EGLImageTargetRenderbufferStorageOES
+ // extension function pointer in the drivers.
+ MarkExtensionUnsupported(OES_EGL_image);
+ }
+
+ if (Vendor() == GLVendor::Imagination && Renderer() == GLRenderer::SGX540) {
+ // Bug 980048
+ MarkExtensionUnsupported(OES_EGL_sync);
+ }
+
+ if (Vendor() == GLVendor::ARM && (Renderer() == GLRenderer::Mali400MP ||
+ Renderer() == GLRenderer::Mali450MP)) {
+ // Bug 1264505
+ MarkExtensionUnsupported(OES_EGL_image_external);
+ }
+
+ if (Renderer() == GLRenderer::AndroidEmulator) {
+ // the Android emulator, which we use to run B2G reftests on,
+ // doesn't expose the OES_rgb8_rgba8 extension, but it seems to
+ // support it (tautologically, as it only runs on desktop GL).
+ MarkExtensionSupported(OES_rgb8_rgba8);
+ }
+
+ if (Vendor() == GLVendor::VMware &&
+ Renderer() == GLRenderer::GalliumLlvmpipe) {
+ // The llvmpipe driver that is used on linux try servers appears to have
+ // buggy support for s3tc/dxt1 compressed textures.
+ // See Bug 975824.
+ MarkExtensionUnsupported(EXT_texture_compression_s3tc);
+ MarkExtensionUnsupported(EXT_texture_compression_dxt1);
+ MarkExtensionUnsupported(ANGLE_texture_compression_dxt3);
+ MarkExtensionUnsupported(ANGLE_texture_compression_dxt5);
+ }
+
+#ifdef XP_MACOSX
+ // Bug 1009642: On OSX Mavericks (10.9), the driver for Intel HD
+ // 3000 appears to be buggy WRT updating sub-images of S3TC
+ // textures with glCompressedTexSubImage2D. Works on Intel HD 4000
+ // and Intel HD 5000/Iris that I tested.
+ // Bug 1124996: Appears to be the same on OSX Yosemite (10.10)
+ if (Renderer() == GLRenderer::IntelHD3000) {
+ MarkExtensionUnsupported(EXT_texture_compression_s3tc);
+ }
+
+ // OSX supports EXT_texture_sRGB in Legacy contexts, but not in Core
+ // contexts. Though EXT_texture_sRGB was included into GL2.1, it *excludes*
+ // the interactions with s3tc. Strictly speaking, you must advertize support
+ // for EXT_texture_sRGB in order to allow for srgb+s3tc on desktop GL. The
+ // omission of EXT_texture_sRGB in OSX Core contexts appears to be a bug.
+ MarkExtensionSupported(EXT_texture_sRGB);
+#endif
+ }
+
+ if (shouldDumpExts) {
+ printf_stderr("\nActivated extensions:\n");
+
+ for (size_t i = 0; i < mAvailableExtensions.size(); i++) {
+ if (!mAvailableExtensions[i]) continue;
+
+ const char* ext = sExtensionNames[i];
+ printf_stderr("[%i] %s\n", (uint32_t)i, ext);
+ }
+ }
+}
+
+void GLContext::PlatformStartup() {
+ RegisterStrongMemoryReporter(new GfxTexturesReporter());
+}
+
+// Common code for checking for both GL extensions and GLX extensions.
+bool GLContext::ListHasExtension(const GLubyte* extensions,
+ const char* extension) {
+ // fix bug 612572 - we were crashing as we were calling this function with
+ // extensions==null
+ if (extensions == nullptr || extension == nullptr) return false;
+
+ const GLubyte* start;
+ GLubyte* where;
+ GLubyte* terminator;
+
+ /* Extension names should not have spaces. */
+ where = (GLubyte*)strchr(extension, ' ');
+ if (where || *extension == '\0') return false;
+
+ /*
+ * It takes a bit of care to be fool-proof about parsing the
+ * OpenGL extensions string. Don't be fooled by sub-strings,
+ * etc.
+ */
+ start = extensions;
+ for (;;) {
+ where = (GLubyte*)strstr((const char*)start, extension);
+ if (!where) {
+ break;
+ }
+ terminator = where + strlen(extension);
+ if (where == start || *(where - 1) == ' ') {
+ if (*terminator == ' ' || *terminator == '\0') {
+ return true;
+ }
+ }
+ start = terminator;
+ }
+ return false;
+}
+
+bool GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) {
+ MOZ_ASSERT(fb);
+
+ ScopedBindFramebuffer autoFB(this, fb);
+ MOZ_GL_ASSERT(this, fIsFramebuffer(fb));
+
+ GLenum status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+ if (pStatus) *pStatus = status;
+
+ return status == LOCAL_GL_FRAMEBUFFER_COMPLETE;
+}
+
+void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
+ GLuint depthRB, GLuint stencilRB, GLuint fb,
+ GLenum target) {
+ MOZ_ASSERT(fb);
+ MOZ_ASSERT(!(colorTex && colorRB));
+
+ ScopedBindFramebuffer autoFB(this, fb);
+ MOZ_GL_ASSERT(this, fIsFramebuffer(fb)); // It only counts after being bound.
+
+ if (colorTex) {
+ MOZ_GL_ASSERT(this, fIsTexture(colorTex));
+ MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
+ target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+ fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ target, colorTex, 0);
+ } else if (colorRB) {
+ // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly.
+ MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB) ||
+ Renderer() == GLRenderer::AndroidEmulator);
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_RENDERBUFFER, colorRB);
+ }
+
+ if (depthRB) {
+ MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB) ||
+ Renderer() == GLRenderer::AndroidEmulator);
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, depthRB);
+ }
+
+ if (stencilRB) {
+ MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB) ||
+ Renderer() == GLRenderer::AndroidEmulator);
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, stencilRB);
+ }
+}
+
+bool GLContext::AssembleOffscreenFBs(const GLuint colorMSRB,
+ const GLuint depthRB,
+ const GLuint stencilRB,
+ const GLuint texture, GLuint* drawFB_out,
+ GLuint* readFB_out) {
+ if (!colorMSRB && !texture) {
+ MOZ_ASSERT(!depthRB && !stencilRB);
+
+ if (drawFB_out) *drawFB_out = 0;
+ if (readFB_out) *readFB_out = 0;
+
+ return true;
+ }
+
+ ScopedBindFramebuffer autoFB(this);
+
+ GLuint drawFB = 0;
+ GLuint readFB = 0;
+
+ if (texture) {
+ readFB = 0;
+ fGenFramebuffers(1, &readFB);
+ BindFB(readFB);
+ fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_TEXTURE_2D, texture, 0);
+ }
+
+ if (colorMSRB) {
+ drawFB = 0;
+ fGenFramebuffers(1, &drawFB);
+ BindFB(drawFB);
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_RENDERBUFFER, colorMSRB);
+ } else {
+ drawFB = readFB;
+ }
+ MOZ_ASSERT(GetIntAs<GLuint>(LOCAL_GL_FRAMEBUFFER_BINDING) == drawFB);
+
+ if (depthRB) {
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, depthRB);
+ }
+
+ if (stencilRB) {
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, stencilRB);
+ }
+
+ // We should be all resized. Check for framebuffer completeness.
+ GLenum status;
+ bool isComplete = true;
+
+ if (!IsFramebufferComplete(drawFB, &status)) {
+ NS_WARNING("DrawFBO: Incomplete");
+#ifdef MOZ_GL_DEBUG_BUILD
+ if (ShouldSpew()) {
+ printf_stderr("Framebuffer status: %X\n", status);
+ }
+#endif
+ isComplete = false;
+ }
+
+ if (!IsFramebufferComplete(readFB, &status)) {
+ NS_WARNING("ReadFBO: Incomplete");
+#ifdef MOZ_GL_DEBUG_BUILD
+ if (ShouldSpew()) {
+ printf_stderr("Framebuffer status: %X\n", status);
+ }
+#endif
+ isComplete = false;
+ }
+
+ if (drawFB_out) {
+ *drawFB_out = drawFB;
+ } else if (drawFB) {
+ MOZ_CRASH("drawFB created when not requested!");
+ }
+
+ if (readFB_out) {
+ *readFB_out = readFB;
+ } else if (readFB) {
+ MOZ_CRASH("readFB created when not requested!");
+ }
+
+ return isComplete;
+}
+
+void GLContext::MarkDestroyed() {
+ if (IsDestroyed()) return;
+
+ OnMarkDestroyed();
+
+ // Null these before they're naturally nulled after dtor, as we want GLContext
+ // to still be alive in *their* dtors.
+ mBlitHelper = nullptr;
+ mReadTexImageHelper = nullptr;
+
+ mContextLost = true;
+ mSymbols = {};
+}
+
+// -
+
+#ifdef MOZ_GL_DEBUG_BUILD
+/* static */
+void GLContext::AssertNotPassingStackBufferToTheGL(const void* ptr) {
+ int somethingOnTheStack;
+ const void* someStackPtr = &somethingOnTheStack;
+ const int page_bits = 12;
+ intptr_t page = reinterpret_cast<uintptr_t>(ptr) >> page_bits;
+ intptr_t someStackPage =
+ reinterpret_cast<uintptr_t>(someStackPtr) >> page_bits;
+ uintptr_t pageDistance = std::abs(page - someStackPage);
+
+ // Explanation for the "distance <= 1" check here as opposed to just
+ // an equality check.
+ //
+ // Here we assume that pages immediately adjacent to the someStackAddress
+ // page, are also stack pages. That allows to catch the case where the calling
+ // frame put a buffer on the stack, and we just crossed the page boundary.
+ // That is likely to happen, precisely, when using stack arrays. I hit that
+ // specifically with CompositorOGL::Initialize.
+ //
+ // In theory we could be unlucky and wrongly assert here. If that happens,
+ // it will only affect debug builds, and looking at stacks we'll be able to
+ // see that this assert is wrong and revert to the conservative and safe
+ // approach of only asserting when address and someStackAddress are
+ // on the same page.
+ bool isStackAddress = pageDistance <= 1;
+ MOZ_ASSERT(!isStackAddress,
+ "Please don't pass stack arrays to the GL. "
+ "Consider using HeapCopyOfStackArray. "
+ "See bug 1005658.");
+}
+
+void GLContext::CreatedProgram(GLContext* aOrigin, GLuint aName) {
+ mTrackedPrograms.AppendElement(NamedResource(aOrigin, aName));
+}
+
+void GLContext::CreatedShader(GLContext* aOrigin, GLuint aName) {
+ mTrackedShaders.AppendElement(NamedResource(aOrigin, aName));
+}
+
+void GLContext::CreatedBuffers(GLContext* aOrigin, GLsizei aCount,
+ GLuint* aNames) {
+ for (GLsizei i = 0; i < aCount; ++i) {
+ mTrackedBuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
+ }
+}
+
+void GLContext::CreatedQueries(GLContext* aOrigin, GLsizei aCount,
+ GLuint* aNames) {
+ for (GLsizei i = 0; i < aCount; ++i) {
+ mTrackedQueries.AppendElement(NamedResource(aOrigin, aNames[i]));
+ }
+}
+
+void GLContext::CreatedTextures(GLContext* aOrigin, GLsizei aCount,
+ GLuint* aNames) {
+ for (GLsizei i = 0; i < aCount; ++i) {
+ mTrackedTextures.AppendElement(NamedResource(aOrigin, aNames[i]));
+ }
+}
+
+void GLContext::CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount,
+ GLuint* aNames) {
+ for (GLsizei i = 0; i < aCount; ++i) {
+ mTrackedFramebuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
+ }
+}
+
+void GLContext::CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
+ GLuint* aNames) {
+ for (GLsizei i = 0; i < aCount; ++i) {
+ mTrackedRenderbuffers.AppendElement(NamedResource(aOrigin, aNames[i]));
+ }
+}
+
+static void RemoveNamesFromArray(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames,
+ nsTArray<GLContext::NamedResource>& aArray) {
+ for (GLsizei j = 0; j < aCount; ++j) {
+ GLuint name = aNames[j];
+ // name 0 can be ignored
+ if (name == 0) continue;
+
+ for (uint32_t i = 0; i < aArray.Length(); ++i) {
+ if (aArray[i].name == name) {
+ aArray.RemoveElementAt(i);
+ break;
+ }
+ }
+ }
+}
+
+void GLContext::DeletedProgram(GLContext* aOrigin, GLuint aName) {
+ RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedPrograms);
+}
+
+void GLContext::DeletedShader(GLContext* aOrigin, GLuint aName) {
+ RemoveNamesFromArray(aOrigin, 1, &aName, mTrackedShaders);
+}
+
+void GLContext::DeletedBuffers(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames) {
+ RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedBuffers);
+}
+
+void GLContext::DeletedQueries(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames) {
+ RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedQueries);
+}
+
+void GLContext::DeletedTextures(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames) {
+ RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedTextures);
+}
+
+void GLContext::DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames) {
+ RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedFramebuffers);
+}
+
+void GLContext::DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames) {
+ RemoveNamesFromArray(aOrigin, aCount, aNames, mTrackedRenderbuffers);
+}
+
+static void MarkContextDestroyedInArray(
+ GLContext* aContext, nsTArray<GLContext::NamedResource>& aArray) {
+ for (uint32_t i = 0; i < aArray.Length(); ++i) {
+ if (aArray[i].origin == aContext) aArray[i].originDeleted = true;
+ }
+}
+
+void GLContext::SharedContextDestroyed(GLContext* aChild) {
+ MarkContextDestroyedInArray(aChild, mTrackedPrograms);
+ MarkContextDestroyedInArray(aChild, mTrackedShaders);
+ MarkContextDestroyedInArray(aChild, mTrackedTextures);
+ MarkContextDestroyedInArray(aChild, mTrackedFramebuffers);
+ MarkContextDestroyedInArray(aChild, mTrackedRenderbuffers);
+ MarkContextDestroyedInArray(aChild, mTrackedBuffers);
+ MarkContextDestroyedInArray(aChild, mTrackedQueries);
+}
+
+static void ReportArrayContents(
+ const char* title, const nsTArray<GLContext::NamedResource>& aArray) {
+ if (aArray.Length() == 0) return;
+
+ printf_stderr("%s:\n", title);
+
+ nsTArray<GLContext::NamedResource> copy(aArray.Clone());
+ copy.Sort();
+
+ GLContext* lastContext = nullptr;
+ for (uint32_t i = 0; i < copy.Length(); ++i) {
+ if (lastContext != copy[i].origin) {
+ if (lastContext) printf_stderr("\n");
+ printf_stderr(" [%p - %s] ", copy[i].origin,
+ copy[i].originDeleted ? "deleted" : "live");
+ lastContext = copy[i].origin;
+ }
+ printf_stderr("%d ", copy[i].name);
+ }
+ printf_stderr("\n");
+}
+
+void GLContext::ReportOutstandingNames() {
+ if (!ShouldSpew()) return;
+
+ printf_stderr("== GLContext %p Outstanding ==\n", this);
+
+ ReportArrayContents("Outstanding Textures", mTrackedTextures);
+ ReportArrayContents("Outstanding Buffers", mTrackedBuffers);
+ ReportArrayContents("Outstanding Queries", mTrackedQueries);
+ ReportArrayContents("Outstanding Programs", mTrackedPrograms);
+ ReportArrayContents("Outstanding Shaders", mTrackedShaders);
+ ReportArrayContents("Outstanding Framebuffers", mTrackedFramebuffers);
+ ReportArrayContents("Outstanding Renderbuffers", mTrackedRenderbuffers);
+}
+
+#endif // ifdef MOZ_GL_DEBUG_BUILD
+
+bool GLContext::IsOffscreenSizeAllowed(const IntSize& aSize) const {
+ int32_t biggerDimension = std::max(aSize.width, aSize.height);
+ int32_t maxAllowed = std::min(mMaxRenderbufferSize, mMaxTextureSize);
+ return biggerDimension <= maxAllowed;
+}
+
+bool GLContext::IsValidOwningThread() const {
+ if (!mOwningThreadId) return true; // Free for all!
+ return PlatformThread::CurrentId() == *mOwningThreadId;
+}
+
+GLBlitHelper* GLContext::BlitHelper() {
+ if (!mBlitHelper) {
+ mBlitHelper.reset(new GLBlitHelper(this));
+ }
+
+ return mBlitHelper.get();
+}
+
+GLReadTexImageHelper* GLContext::ReadTexImageHelper() {
+ if (!mReadTexImageHelper) {
+ mReadTexImageHelper = MakeUnique<GLReadTexImageHelper>(this);
+ }
+
+ return mReadTexImageHelper.get();
+}
+
+void GLContext::FlushIfHeavyGLCallsSinceLastFlush() {
+ if (!mHeavyGLCallsSinceLastFlush) {
+ return;
+ }
+ if (MakeCurrent()) {
+ fFlush();
+ }
+}
+
+/*static*/
+bool GLContext::ShouldDumpExts() { return gfxEnv::MOZ_GL_DUMP_EXTS(); }
+
+bool DoesStringMatch(const char* aString, const char* aWantedString) {
+ if (!aString || !aWantedString) return false;
+
+ const char* occurrence = strstr(aString, aWantedString);
+
+ // aWanted not found
+ if (!occurrence) return false;
+
+ // aWantedString preceded by alpha character
+ if (occurrence != aString && isalpha(*(occurrence - 1))) return false;
+
+ // aWantedVendor followed by alpha character
+ const char* afterOccurrence = occurrence + strlen(aWantedString);
+ if (isalpha(*afterOccurrence)) return false;
+
+ return true;
+}
+
+/*static*/
+bool GLContext::ShouldSpew() { return gfxEnv::MOZ_GL_SPEW(); }
+
+void SplitByChar(const nsACString& str, const char delim,
+ std::vector<nsCString>* const out) {
+ uint32_t start = 0;
+ while (true) {
+ int32_t end = str.FindChar(' ', start);
+ if (end == -1) break;
+
+ uint32_t len = (uint32_t)end - start;
+ nsDependentCSubstring substr(str, start, len);
+ out->push_back(nsCString(substr));
+
+ start = end + 1;
+ }
+
+ nsDependentCSubstring substr(str, start);
+ out->push_back(nsCString(substr));
+}
+
+void GLContext::fCopyTexImage2D(GLenum target, GLint level,
+ GLenum internalformat, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLint border) {
+ if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
+ // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
+ // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
+ level = -1;
+ width = -1;
+ height = -1;
+ border = -1;
+ }
+
+ BeforeGLReadCall();
+ raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height,
+ border);
+ AfterGLReadCall();
+}
+
+void GLContext::fGetIntegerv(const GLenum pname, GLint* const params) const {
+ const auto AssertBinding = [&](const char* const name, const GLenum binding,
+ const GLuint expected) {
+ if (MOZ_LIKELY(!mDebugFlags)) return;
+ GLuint actual = 0;
+ raw_fGetIntegerv(binding, (GLint*)&actual);
+ if (actual != expected) {
+ gfxCriticalError() << "Misprediction: " << name << " expected "
+ << expected << ", was " << actual;
+ }
+ };
+
+ switch (pname) {
+ case LOCAL_GL_MAX_TEXTURE_SIZE:
+ MOZ_ASSERT(mMaxTextureSize > 0);
+ *params = mMaxTextureSize;
+ return;
+
+ case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ MOZ_ASSERT(mMaxCubeMapTextureSize > 0);
+ *params = mMaxCubeMapTextureSize;
+ return;
+
+ case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
+ MOZ_ASSERT(mMaxRenderbufferSize > 0);
+ *params = mMaxRenderbufferSize;
+ return;
+
+ case LOCAL_GL_VIEWPORT:
+ for (size_t i = 0; i < 4; i++) {
+ params[i] = mViewportRect[i];
+ }
+ return;
+
+ case LOCAL_GL_SCISSOR_BOX:
+ for (size_t i = 0; i < 4; i++) {
+ params[i] = mScissorRect[i];
+ }
+ return;
+
+ case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING:
+ if (mElideDuplicateBindFramebuffers) {
+ static_assert(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING ==
+ LOCAL_GL_FRAMEBUFFER_BINDING);
+ AssertBinding("GL_DRAW_FRAMEBUFFER_BINDING",
+ LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, mCachedDrawFb);
+ *params = static_cast<GLint>(mCachedDrawFb);
+ return;
+ }
+ break;
+
+ case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
+ if (mElideDuplicateBindFramebuffers) {
+ if (IsSupported(GLFeature::framebuffer_blit)) {
+ AssertBinding("GL_READ_FRAMEBUFFER_BINDING",
+ LOCAL_GL_READ_FRAMEBUFFER_BINDING, mCachedReadFb);
+ }
+ *params = static_cast<GLint>(mCachedReadFb);
+ return;
+ }
+ break;
+
+ default:
+ break;
+ }
+ raw_fGetIntegerv(pname, params);
+}
+
+void GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid* pixels) {
+ BeforeGLReadCall();
+ raw_fReadPixels(x, y, width, height, format, type, pixels);
+ AfterGLReadCall();
+
+ // Check if GL is giving back 1.0 alpha for
+ // RGBA reads to RGBA images from no-alpha buffers.
+#ifdef XP_MACOSX
+ if (WorkAroundDriverBugs() && Vendor() == gl::GLVendor::NVIDIA &&
+ format == LOCAL_GL_RGBA && type == LOCAL_GL_UNSIGNED_BYTE &&
+ !IsCoreProfile() && width && height) {
+ GLint alphaBits = 0;
+ fGetIntegerv(LOCAL_GL_ALPHA_BITS, &alphaBits);
+ if (!alphaBits) {
+ const uint32_t alphaMask = 0xff000000;
+
+ uint32_t* itr = (uint32_t*)pixels;
+ uint32_t testPixel = *itr;
+ if ((testPixel & alphaMask) != alphaMask) {
+ // We need to set the alpha channel to 1.0 manually.
+ uint32_t* itrEnd =
+ itr + width * height; // Stride is guaranteed to be width*4.
+
+ for (; itr != itrEnd; itr++) {
+ *itr |= alphaMask;
+ }
+ }
+ }
+ }
+#endif
+}
+
+void GLContext::fDeleteFramebuffers(GLsizei n, const GLuint* names) {
+ // Avoid crash by flushing before glDeleteFramebuffers. See bug 1194923.
+ if (mNeedsFlushBeforeDeleteFB) {
+ fFlush();
+ }
+
+ if (n == 1 && *names == 0) {
+ // Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
+ } else {
+ raw_fDeleteFramebuffers(n, names);
+ }
+ TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
+}
+
+#ifdef MOZ_WIDGET_ANDROID
+/**
+ * Conservatively estimate whether there is enough available
+ * contiguous virtual address space to map a newly allocated texture.
+ */
+static bool WillTextureMapSucceed(GLsizei width, GLsizei height, GLenum format,
+ GLenum type) {
+ bool willSucceed = false;
+ // Some drivers leave large gaps between textures, so require
+ // there to be double the actual size of the texture available.
+ size_t size = width * height * GetBytesPerTexel(format, type) * 2;
+
+ void* p = mmap(nullptr, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (p != MAP_FAILED) {
+ willSucceed = true;
+ munmap(p, size);
+ }
+
+ return willSucceed;
+}
+#endif // MOZ_WIDGET_ANDROID
+
+void GLContext::fTexImage2D(GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const GLvoid* pixels) {
+ if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
+ // pass wrong values to cause the GL to generate GL_INVALID_VALUE.
+ // See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
+ level = -1;
+ width = -1;
+ height = -1;
+ border = -1;
+ }
+#if MOZ_WIDGET_ANDROID
+ if (mTextureAllocCrashesOnMapFailure) {
+ // We have no way of knowing whether this texture already has
+ // storage allocated for it, and therefore whether this check
+ // is necessary. We must therefore assume it does not and
+ // always perform the check.
+ if (!WillTextureMapSucceed(width, height, internalformat, type)) {
+ return;
+ }
+ }
+#endif
+ raw_fTexImage2D(target, level, internalformat, width, height, border, format,
+ type, pixels);
+}
+
+UniquePtr<Texture> CreateTexture(GLContext& gl, const gfx::IntSize& size) {
+ const GLenum target = LOCAL_GL_TEXTURE_2D;
+ const GLenum format = LOCAL_GL_RGBA;
+
+ auto tex = MakeUnique<Texture>(gl);
+ ScopedBindTexture autoTex(&gl, tex->name, target);
+
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+ gl.fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+
+ gl.fTexImage2D(target, 0, format, size.width, size.height, 0, format,
+ LOCAL_GL_UNSIGNED_BYTE, nullptr);
+
+ return tex;
+}
+
+uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
+ // If there is no defined format or type, we're not taking up any memory
+ if (!format || !type) {
+ return 0;
+ }
+
+ if (format == LOCAL_GL_DEPTH_COMPONENT) {
+ if (type == LOCAL_GL_UNSIGNED_SHORT)
+ return 2;
+ else if (type == LOCAL_GL_UNSIGNED_INT)
+ return 4;
+ } else if (format == LOCAL_GL_DEPTH_STENCIL) {
+ if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT) return 4;
+ }
+
+ if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT ||
+ type == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
+ uint32_t multiplier = type == LOCAL_GL_UNSIGNED_BYTE ? 1 : 4;
+ switch (format) {
+ case LOCAL_GL_ALPHA:
+ case LOCAL_GL_LUMINANCE:
+ case LOCAL_GL_R8:
+ return 1 * multiplier;
+ case LOCAL_GL_LUMINANCE_ALPHA:
+ case LOCAL_GL_R16:
+ return 2 * multiplier;
+ case LOCAL_GL_RGB:
+ return 3 * multiplier;
+ case LOCAL_GL_RGBA:
+ case LOCAL_GL_BGRA_EXT:
+ return 4 * multiplier;
+ default:
+ break;
+ }
+ } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
+ type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
+ type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
+ type == LOCAL_GL_UNSIGNED_SHORT) {
+ return 2;
+ }
+
+ gfxCriticalError() << "Unknown texture type " << type << " or format "
+ << format;
+ return 0;
+}
+
+void GLContext::ResetTLSCurrentContext() {
+ if (sCurrentContext.init()) {
+ sCurrentContext.set(nullptr);
+ }
+}
+
+bool GLContext::MakeCurrent(bool aForce) const {
+ if (MOZ_UNLIKELY(IsContextLost())) return false;
+
+ if (MOZ_LIKELY(!aForce)) {
+ bool isCurrent;
+ if (mUseTLSIsCurrent && sCurrentContext.init()) {
+ isCurrent = (sCurrentContext.get() == this);
+ } else {
+ isCurrent = IsCurrentImpl();
+ }
+ if (MOZ_LIKELY(isCurrent)) {
+ MOZ_ASSERT(IsCurrentImpl() ||
+ MakeCurrentImpl()); // Might have lost context.
+ return true;
+ }
+ }
+ if (!IsValidOwningThread()) {
+ gfxCriticalError() << "MakeCurrent called on a thread other than the"
+ << " creating thread!";
+ if (gfxEnv::MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) {
+ MOZ_CRASH("MOZ_GL_RELEASE_ASSERT_CONTEXT_OWNERSHIP");
+ }
+ }
+ if (!MakeCurrentImpl()) return false;
+
+ if (sCurrentContext.init()) {
+ sCurrentContext.set(this);
+ }
+ return true;
+}
+
+void GLContext::ResetSyncCallCount(const char* resetReason) const {
+ if (ShouldSpew()) {
+ printf_stderr("On %s, mSyncGLCallCount = %" PRIu64 "\n", resetReason,
+ mSyncGLCallCount);
+ }
+
+ mSyncGLCallCount = 0;
+}
+
+// -
+
+bool CheckContextLost(const GLContext* const gl) {
+ return gl->CheckContextLost();
+}
+
+// -
+
+GLenum GLContext::GetError() const {
+ if (mContextLost) return LOCAL_GL_CONTEXT_LOST;
+
+ if (mImplicitMakeCurrent) {
+ (void)MakeCurrent();
+ }
+
+ const auto fnGetError = [&]() {
+ const auto ret = mSymbols.fGetError();
+ if (ret == LOCAL_GL_CONTEXT_LOST) {
+ OnContextLostError();
+ mTopError = ret; // Promote to top!
+ }
+ return ret;
+ };
+
+ auto ret = fnGetError();
+
+ {
+ auto flushedErr = ret;
+ uint32_t i = 1;
+ while (flushedErr && !mContextLost) {
+ if (i == 100) {
+ gfxCriticalError() << "Flushing glGetError still "
+ << gfx::hexa(flushedErr) << " after " << i
+ << " calls.";
+ break;
+ }
+ flushedErr = fnGetError();
+ i += 1;
+ }
+ }
+
+ if (mTopError) {
+ ret = mTopError;
+ mTopError = 0;
+ }
+
+ if (mDebugFlags & DebugFlagTrace) {
+ const auto errStr = GLErrorToString(ret);
+ printf_stderr("[gl:%p] GetError() -> %s\n", this, errStr.c_str());
+ }
+ return ret;
+}
+
+GLenum GLContext::fGetGraphicsResetStatus() const {
+ OnSyncCall();
+
+ GLenum ret = 0;
+ if (mSymbols.fGetGraphicsResetStatus) {
+ if (mImplicitMakeCurrent) {
+ (void)MakeCurrent();
+ }
+ ret = mSymbols.fGetGraphicsResetStatus();
+ } else {
+ if (!MakeCurrent(true)) {
+ ret = LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB;
+ }
+ }
+
+ if (mDebugFlags & DebugFlagTrace) {
+ printf_stderr("[gl:%p] GetGraphicsResetStatus() -> 0x%04x\n", this, ret);
+ }
+
+ return ret;
+}
+
+void GLContext::OnContextLostError() const {
+ if (mDebugFlags & DebugFlagTrace) {
+ printf_stderr("[gl:%p] CONTEXT_LOST\n", this);
+ }
+ mContextLost = true;
+}
+
+// --
+
+/*static*/ std::string GLContext::GLErrorToString(const GLenum err) {
+ switch (err) {
+ case LOCAL_GL_NO_ERROR:
+ return "GL_NO_ERROR";
+ case LOCAL_GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case LOCAL_GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case LOCAL_GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case LOCAL_GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case LOCAL_GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case LOCAL_GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
+ case LOCAL_GL_TABLE_TOO_LARGE:
+ return "GL_TABLE_TOO_LARGE";
+ case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
+ return "GL_INVALID_FRAMEBUFFER_OPERATION";
+ case LOCAL_GL_CONTEXT_LOST:
+ return "GL_CONTEXT_LOST";
+ }
+
+ const nsPrintfCString hex("<enum 0x%04x>", err);
+ return hex.BeginReading();
+}
+
+// --
+
+void GLContext::BeforeGLCall_Debug(const char* const funcName) const {
+ MOZ_ASSERT(mDebugFlags);
+
+ if (mDebugFlags & DebugFlagTrace) {
+ printf_stderr("[gl:%p] > %s\n", this, funcName);
+ }
+
+ MOZ_ASSERT(!mDebugErrorScope);
+ mDebugErrorScope.reset(new LocalErrorScope(*this));
+}
+
+void GLContext::AfterGLCall_Debug(const char* const funcName) const {
+ MOZ_ASSERT(mDebugFlags);
+
+ // calling fFinish() immediately after every GL call makes sure that if this
+ // GL command crashes, the stack trace will actually point to it. Otherwise,
+ // OpenGL being an asynchronous API, stack traces tend to be meaningless
+ mSymbols.fFinish();
+
+ const auto err = mDebugErrorScope->GetError();
+ mDebugErrorScope = nullptr;
+ if (!mTopError) {
+ mTopError = err;
+ }
+
+ if (mDebugFlags & DebugFlagTrace) {
+ printf_stderr("[gl:%p] < %s [%s]\n", this, funcName,
+ GLErrorToString(err).c_str());
+ }
+
+ if (err && !mLocalErrorScopeStack.size()) {
+ const auto errStr = GLErrorToString(err);
+ const auto text = nsPrintfCString("%s: Generated unexpected %s error",
+ funcName, errStr.c_str());
+ printf_stderr("[gl:%p] %s.\n", this, text.BeginReading());
+
+ const bool abortOnError = mDebugFlags & DebugFlagAbortOnError;
+ if (abortOnError && err != LOCAL_GL_CONTEXT_LOST) {
+ gfxCriticalErrorOnce() << text.BeginReading();
+ MOZ_CRASH(
+ "Aborting... (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)");
+ }
+ }
+}
+
+/*static*/
+void GLContext::OnImplicitMakeCurrentFailure(const char* const funcName) {
+ gfxCriticalError() << "Ignoring call to " << funcName << " with failed"
+ << " mImplicitMakeCurrent.";
+}
+
+bool GLContext::CreateOffscreenDefaultFb(const gfx::IntSize& size) {
+ mOffscreenDefaultFb = MozFramebuffer::Create(this, size, 0, true);
+ return bool(mOffscreenDefaultFb);
+}
+
+// Some of Mesa's drivers allocate heap memory when loaded and don't
+// free it when unloaded; this causes Leak Sanitizer to detect leaks and
+// fail to unwind the stack, so suppressions don't work. This
+// workaround leaks a reference to the driver library so that it's never
+// unloaded. Because the leak isn't significant for real usage, only
+// ASan runs in CI, this is applied only to the software renderer.
+//
+// See bug 1702394 for more details.
+void MesaMemoryLeakWorkaround() {
+#if defined(XP_LINUX) && !defined(ANDROID)
+ Maybe<nsAutoCString> foundPath;
+
+ dl_iterate_phdr(
+ [](dl_phdr_info* info, size_t size, void* data) {
+ auto& foundPath = *reinterpret_cast<Maybe<nsAutoCString>*>(data);
+ nsDependentCString thisPath(info->dlpi_name);
+ if (StringEndsWith(thisPath, "/swrast_dri.so"_ns)) {
+ foundPath.emplace(thisPath);
+ return 1;
+ }
+ return 0;
+ },
+ &foundPath);
+
+ if (foundPath) {
+ // Deliberately leak to prevent unload
+ Unused << dlopen(foundPath->get(), RTLD_LAZY);
+ }
+#endif // XP_LINUX but not ANDROID
+}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h
new file mode 100644
index 0000000000..eea26024ae
--- /dev/null
+++ b/gfx/gl/GLContext.h
@@ -0,0 +1,3883 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXT_H_
+#define GLCONTEXT_H_
+
+#include <bitset>
+#include <stdint.h>
+#include <stdio.h>
+#include <stack>
+#include <vector>
+
+#ifdef DEBUG
+# include <string.h>
+#endif
+
+#ifdef GetClassName
+# undef GetClassName
+#endif
+
+// Define MOZ_GL_DEBUG_BUILD unconditionally to enable GL debugging in opt
+// builds.
+#ifdef DEBUG
+# define MOZ_GL_DEBUG_BUILD 1
+#endif
+
+#include "mozilla/IntegerRange.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/ThreadLocal.h"
+
+#include "MozFramebuffer.h"
+#include "nsTArray.h"
+#include "GLConsts.h"
+#include "GLDefs.h"
+#include "GLTypes.h"
+#include "nsRegionFwd.h"
+#include "nsString.h"
+#include "GLContextTypes.h"
+#include "GLContextSymbols.h"
+#include "base/platform_thread.h" // for PlatformThreadId
+#include "mozilla/GenericRefCounted.h"
+#include "mozilla/WeakPtr.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/ProfilerLabels.h"
+#endif
+
+namespace mozilla {
+
+namespace gl {
+class GLBlitHelper;
+class GLLibraryEGL;
+class GLReadTexImageHelper;
+class SharedSurface;
+class SymbolLoader;
+struct SymLoadStruct;
+} // namespace gl
+
+namespace layers {
+class ColorTextureLayerProgram;
+} // namespace layers
+
+namespace widget {
+class CompositorWidget;
+} // namespace widget
+} // namespace mozilla
+
+namespace mozilla {
+namespace gl {
+
+enum class GLFeature {
+ bind_buffer_offset,
+ blend_minmax,
+ clear_buffers,
+ copy_buffer,
+ depth_texture,
+ draw_buffers,
+ draw_buffers_indexed,
+ draw_instanced,
+ element_index_uint,
+ ES2_compatibility,
+ ES3_compatibility,
+ EXT_color_buffer_float,
+ frag_color_float,
+ frag_depth,
+ framebuffer_blit,
+ framebuffer_multisample,
+ framebuffer_object,
+ framebuffer_object_EXT_OES,
+ get_integer_indexed,
+ get_integer64_indexed,
+ get_query_object_i64v,
+ get_query_object_iv,
+ gpu_shader4,
+ instanced_arrays,
+ instanced_non_arrays,
+ internalformat_query,
+ invalidate_framebuffer,
+ map_buffer_range,
+ multiview,
+ occlusion_query,
+ occlusion_query_boolean,
+ occlusion_query2,
+ packed_depth_stencil,
+ prim_restart,
+ prim_restart_fixed,
+ provoking_vertex,
+ query_counter,
+ query_objects,
+ query_time_elapsed,
+ read_buffer,
+ renderbuffer_color_float,
+ renderbuffer_color_half_float,
+ robust_buffer_access_behavior,
+ robustness,
+ sRGB,
+ sampler_objects,
+ seamless_cube_map_opt_in,
+ shader_texture_lod,
+ split_framebuffer,
+ standard_derivatives,
+ sync,
+ texture_3D,
+ texture_3D_compressed,
+ texture_3D_copy,
+ texture_compression_bptc,
+ texture_compression_rgtc,
+ texture_float,
+ texture_float_linear,
+ texture_half_float,
+ texture_half_float_linear,
+ texture_non_power_of_two,
+ texture_norm16,
+ texture_rg,
+ texture_storage,
+ texture_swizzle,
+ transform_feedback2,
+ uniform_buffer_object,
+ uniform_matrix_nonsquare,
+ vertex_array_object,
+ EnumMax
+};
+
+enum class ContextProfile : uint8_t {
+ Unknown = 0,
+ OpenGLCore,
+ OpenGLCompatibility,
+ OpenGLES
+};
+
+enum class GLRenderer {
+ Adreno200,
+ Adreno205,
+ AdrenoTM200,
+ AdrenoTM205,
+ AdrenoTM305,
+ AdrenoTM320,
+ AdrenoTM330,
+ AdrenoTM420,
+ Mali400MP,
+ Mali450MP,
+ MaliT,
+ SGX530,
+ SGX540,
+ SGX544MP,
+ Tegra,
+ AndroidEmulator,
+ GalliumLlvmpipe,
+ IntelHD3000,
+ MicrosoftBasicRenderDriver,
+ SamsungXclipse,
+ Other
+};
+
+class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
+ public:
+ static MOZ_THREAD_LOCAL(const GLContext*) sCurrentContext;
+
+ static void InvalidateCurrentContext();
+
+ const GLContextDesc mDesc;
+
+ bool mImplicitMakeCurrent = false;
+ bool mUseTLSIsCurrent;
+
+ static void ResetTLSCurrentContext();
+
+ class TlsScope final {
+ const WeakPtr<GLContext> mGL;
+ const bool mWasTlsOk;
+
+ public:
+ explicit TlsScope(GLContext* const gl, bool invalidate = false)
+ : mGL(gl), mWasTlsOk(gl && gl->mUseTLSIsCurrent) {
+ if (mGL) {
+ if (invalidate) {
+ InvalidateCurrentContext();
+ }
+ mGL->mUseTLSIsCurrent = true;
+ }
+ }
+
+ ~TlsScope() {
+ if (mGL) {
+ mGL->mUseTLSIsCurrent = mWasTlsOk;
+ }
+ }
+ };
+
+ // -----------------------------------------------------------------------------
+ // basic getters
+ public:
+ /**
+ * Returns true if the context is using ANGLE. This should only be overridden
+ * for an ANGLE implementation.
+ */
+ virtual bool IsANGLE() const { return false; }
+
+ /**
+ * Returns true if the context is using WARP. This should only be overridden
+ * for an ANGLE implementation.
+ */
+ virtual bool IsWARP() const { return false; }
+
+ virtual void GetWSIInfo(nsCString* const out) const = 0;
+
+ /**
+ * Return true if we are running on a OpenGL core profile context
+ */
+ inline bool IsCoreProfile() const {
+ MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+ return mProfile == ContextProfile::OpenGLCore;
+ }
+
+ /**
+ * Return true if we are running on a OpenGL compatibility profile context
+ * (legacy profile 2.1 on Max OS X)
+ */
+ inline bool IsCompatibilityProfile() const {
+ MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+ return mProfile == ContextProfile::OpenGLCompatibility;
+ }
+
+ inline bool IsGLES() const {
+ MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+
+ return mProfile == ContextProfile::OpenGLES;
+ }
+
+ inline bool IsAtLeast(ContextProfile profile, unsigned int version) const {
+ MOZ_ASSERT(profile != ContextProfile::Unknown,
+ "IsAtLeast: bad <profile> parameter");
+ MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
+ MOZ_ASSERT(mVersion != 0, "unknown context version");
+
+ if (version > mVersion) {
+ return false;
+ }
+
+ return profile == mProfile;
+ }
+
+ /**
+ * Return the version of the context.
+ * Example :
+ * If this a OpenGL 2.1, that will return 210
+ */
+ inline uint32_t Version() const { return mVersion; }
+
+ inline uint32_t ShadingLanguageVersion() const {
+ return mShadingLanguageVersion;
+ }
+
+ GLVendor Vendor() const { return mVendor; }
+ GLRenderer Renderer() const { return mRenderer; }
+ bool IsMesa() const { return mIsMesa; }
+
+ bool IsContextLost() const { return mContextLost; }
+
+ bool CheckContextLost() const {
+ mTopError = GetError();
+ return IsContextLost();
+ }
+
+ bool HasPBOState() const { return (!IsGLES() || Version() >= 300); }
+
+ /**
+ * If this context is double-buffered, returns TRUE.
+ */
+ virtual bool IsDoubleBuffered() const { return false; }
+
+ virtual GLContextType GetContextType() const = 0;
+
+ virtual bool IsCurrentImpl() const = 0;
+ virtual bool MakeCurrentImpl() const = 0;
+
+ bool IsCurrent() const {
+ if (mImplicitMakeCurrent) return MakeCurrent();
+
+ return IsCurrentImpl();
+ }
+
+ bool MakeCurrent(bool aForce = false) const;
+
+ /**
+ * Get the default framebuffer for this context.
+ */
+ UniquePtr<MozFramebuffer> mOffscreenDefaultFb;
+
+ bool CreateOffscreenDefaultFb(const gfx::IntSize& size);
+
+ virtual GLuint GetDefaultFramebuffer() {
+ if (mOffscreenDefaultFb) {
+ return mOffscreenDefaultFb->mFB;
+ }
+ return 0;
+ }
+
+ /**
+ * mVersion store the OpenGL's version, multiplied by 100. For example, if
+ * the context is an OpenGL 2.1 context, mVersion value will be 210.
+ */
+ uint32_t mVersion = 0;
+ ContextProfile mProfile = ContextProfile::Unknown;
+
+ uint32_t mShadingLanguageVersion = 0;
+
+ GLVendor mVendor = GLVendor::Other;
+ GLRenderer mRenderer = GLRenderer::Other;
+ bool mIsMesa = false;
+
+ // -----------------------------------------------------------------------------
+ // Extensions management
+ /**
+ * This mechanism is designed to know if an extension is supported. In the
+ * long term, we would like to only use the extension group queries XXX_* to
+ * have full compatibility with context version and profiles (especialy the
+ * core that officialy don't bring any extensions).
+ */
+
+ /**
+ * Known GL extensions that can be queried by
+ * IsExtensionSupported. The results of this are cached, and as
+ * such it's safe to use this even in performance critical code.
+ * If you add to this array, remember to add to the string names
+ * in GLContext.cpp.
+ */
+ enum GLExtensions {
+ Extension_None = 0,
+ AMD_compressed_ATC_texture,
+ ANGLE_depth_texture,
+ ANGLE_framebuffer_blit,
+ ANGLE_framebuffer_multisample,
+ ANGLE_instanced_arrays,
+ ANGLE_multiview,
+ ANGLE_provoking_vertex,
+ ANGLE_texture_compression_dxt3,
+ ANGLE_texture_compression_dxt5,
+ ANGLE_timer_query,
+ APPLE_client_storage,
+ APPLE_fence,
+ APPLE_framebuffer_multisample,
+ APPLE_sync,
+ APPLE_texture_range,
+ APPLE_vertex_array_object,
+ ARB_ES2_compatibility,
+ ARB_ES3_compatibility,
+ ARB_color_buffer_float,
+ ARB_compatibility,
+ ARB_copy_buffer,
+ ARB_depth_texture,
+ ARB_draw_buffers,
+ ARB_draw_instanced,
+ ARB_framebuffer_object,
+ ARB_framebuffer_sRGB,
+ ARB_geometry_shader4,
+ ARB_half_float_pixel,
+ ARB_instanced_arrays,
+ ARB_internalformat_query,
+ ARB_invalidate_subdata,
+ ARB_map_buffer_range,
+ ARB_occlusion_query2,
+ ARB_pixel_buffer_object,
+ ARB_provoking_vertex,
+ ARB_robust_buffer_access_behavior,
+ ARB_robustness,
+ ARB_sampler_objects,
+ ARB_seamless_cube_map,
+ ARB_shader_texture_lod,
+ ARB_sync,
+ ARB_texture_compression,
+ ARB_texture_compression_bptc,
+ ARB_texture_compression_rgtc,
+ ARB_texture_float,
+ ARB_texture_non_power_of_two,
+ ARB_texture_rectangle,
+ ARB_texture_rg,
+ ARB_texture_storage,
+ ARB_texture_swizzle,
+ ARB_timer_query,
+ ARB_transform_feedback2,
+ ARB_uniform_buffer_object,
+ ARB_vertex_array_object,
+ CHROMIUM_color_buffer_float_rgb,
+ CHROMIUM_color_buffer_float_rgba,
+ EXT_bgra,
+ EXT_blend_minmax,
+ EXT_color_buffer_float,
+ EXT_color_buffer_half_float,
+ EXT_copy_texture,
+ EXT_disjoint_timer_query,
+ EXT_draw_buffers,
+ EXT_draw_buffers2,
+ EXT_draw_instanced,
+ EXT_float_blend,
+ EXT_frag_depth,
+ EXT_framebuffer_blit,
+ EXT_framebuffer_multisample,
+ EXT_framebuffer_object,
+ EXT_framebuffer_sRGB,
+ EXT_gpu_shader4,
+ EXT_map_buffer_range,
+ EXT_multisampled_render_to_texture,
+ EXT_occlusion_query_boolean,
+ EXT_packed_depth_stencil,
+ EXT_provoking_vertex,
+ EXT_read_format_bgra,
+ EXT_robustness,
+ EXT_sRGB,
+ EXT_sRGB_write_control,
+ EXT_shader_texture_lod,
+ EXT_texture_compression_bptc,
+ EXT_texture_compression_dxt1,
+ EXT_texture_compression_rgtc,
+ EXT_texture_compression_s3tc,
+ EXT_texture_compression_s3tc_srgb,
+ EXT_texture_filter_anisotropic,
+ EXT_texture_format_BGRA8888,
+ EXT_texture_norm16,
+ EXT_texture_sRGB,
+ EXT_texture_storage,
+ EXT_timer_query,
+ EXT_transform_feedback,
+ EXT_unpack_subimage,
+ IMG_read_format,
+ IMG_texture_compression_pvrtc,
+ IMG_texture_npot,
+ KHR_debug,
+ KHR_parallel_shader_compile,
+ KHR_robust_buffer_access_behavior,
+ KHR_robustness,
+ KHR_texture_compression_astc_hdr,
+ KHR_texture_compression_astc_ldr,
+ NV_draw_instanced,
+ NV_fence,
+ NV_framebuffer_blit,
+ NV_geometry_program4,
+ NV_half_float,
+ NV_instanced_arrays,
+ NV_primitive_restart,
+ NV_texture_barrier,
+ NV_transform_feedback,
+ NV_transform_feedback2,
+ OES_EGL_image,
+ OES_EGL_image_external,
+ OES_EGL_sync,
+ OES_compressed_ETC1_RGB8_texture,
+ OES_depth24,
+ OES_depth32,
+ OES_depth_texture,
+ OES_draw_buffers_indexed,
+ OES_element_index_uint,
+ OES_fbo_render_mipmap,
+ OES_framebuffer_object,
+ OES_packed_depth_stencil,
+ OES_rgb8_rgba8,
+ OES_standard_derivatives,
+ OES_stencil8,
+ OES_texture_3D,
+ OES_texture_float,
+ OES_texture_float_linear,
+ OES_texture_half_float,
+ OES_texture_half_float_linear,
+ OES_texture_npot,
+ OES_vertex_array_object,
+ OVR_multiview2,
+ Extensions_Max,
+ Extensions_End
+ };
+
+ bool IsExtensionSupported(GLExtensions aKnownExtension) const {
+ return mAvailableExtensions[aKnownExtension];
+ }
+
+ protected:
+ void MarkExtensionUnsupported(GLExtensions aKnownExtension) {
+ mAvailableExtensions[aKnownExtension] = 0;
+ }
+
+ void MarkExtensionSupported(GLExtensions aKnownExtension) {
+ mAvailableExtensions[aKnownExtension] = 1;
+ }
+
+ std::bitset<Extensions_Max> mAvailableExtensions;
+
+ // -----------------------------------------------------------------------------
+ // Feature queries
+ /*
+ * This mecahnism introduces a new way to check if a OpenGL feature is
+ * supported, regardless of whether it is supported by an extension or
+ * natively by the context version/profile
+ */
+ public:
+ bool IsSupported(GLFeature feature) const {
+ return mAvailableFeatures[size_t(feature)];
+ }
+
+ static const char* GetFeatureName(GLFeature feature);
+
+ private:
+ std::bitset<size_t(GLFeature::EnumMax)> mAvailableFeatures;
+
+ /**
+ * Init features regarding OpenGL extension and context version and profile
+ */
+ void InitFeatures();
+
+ /**
+ * Mark the feature and associated extensions as unsupported
+ */
+ void MarkUnsupported(GLFeature feature);
+
+ /**
+ * Is this feature supported using the core (unsuffixed) symbols?
+ */
+ bool IsFeatureProvidedByCoreSymbols(GLFeature feature);
+
+ // -----------------------------------------------------------------------------
+ // Error handling
+
+ private:
+ mutable bool mContextLost = false;
+ mutable GLenum mTopError = 0;
+
+ protected:
+ void OnContextLostError() const;
+
+ public:
+ static std::string GLErrorToString(GLenum aError);
+
+ static bool IsBadCallError(const GLenum err) {
+ return !(err == 0 || err == LOCAL_GL_CONTEXT_LOST);
+ }
+
+ class LocalErrorScope;
+
+ private:
+ mutable std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
+ mutable UniquePtr<LocalErrorScope> mDebugErrorScope;
+
+ ////////////////////////////////////
+ // Use this safer option.
+
+ public:
+ class LocalErrorScope {
+ const GLContext& mGL;
+ GLenum mOldTop;
+ bool mHasBeenChecked;
+
+ public:
+ explicit LocalErrorScope(const GLContext& gl)
+ : mGL(gl), mHasBeenChecked(false) {
+ mGL.mLocalErrorScopeStack.push(this);
+ mOldTop = mGL.GetError();
+ }
+
+ /// Never returns CONTEXT_LOST.
+ GLenum GetError() {
+ MOZ_ASSERT(!mHasBeenChecked);
+ mHasBeenChecked = true;
+
+ const auto ret = mGL.GetError();
+ if (ret == LOCAL_GL_CONTEXT_LOST) return 0;
+ return ret;
+ }
+
+ ~LocalErrorScope() {
+ MOZ_ASSERT(mHasBeenChecked);
+
+ MOZ_ASSERT(!IsBadCallError(mGL.GetError()));
+
+ MOZ_ASSERT(mGL.mLocalErrorScopeStack.top() == this);
+ mGL.mLocalErrorScopeStack.pop();
+
+ mGL.mTopError = mOldTop;
+ }
+ };
+
+ // -
+
+ bool GetPotentialInteger(GLenum pname, GLint* param) {
+ LocalErrorScope localError(*this);
+
+ fGetIntegerv(pname, param);
+
+ GLenum err = localError.GetError();
+ MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_INVALID_ENUM);
+ return err == LOCAL_GL_NO_ERROR;
+ }
+
+ void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
+ GLsizei length, const GLchar* message);
+
+ private:
+ static void GLAPIENTRY StaticDebugCallback(GLenum source, GLenum type,
+ GLuint id, GLenum severity,
+ GLsizei length,
+ const GLchar* message,
+ const GLvoid* userParam);
+
+ // -----------------------------------------------------------------------------
+ // Debugging implementation
+ private:
+#ifndef MOZ_FUNCTION_NAME
+# ifdef __GNUC__
+# define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
+# elif defined(_MSC_VER)
+# define MOZ_FUNCTION_NAME __FUNCTION__
+# else
+# define MOZ_FUNCTION_NAME \
+ __func__ // defined in C99, supported in various C++ compilers. Just raw
+ // function name.
+# endif
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+// Record the name of the GL call for better hang stacks on Android.
+# define ANDROID_ONLY_PROFILER_LABEL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
+#else
+# define ANDROID_ONLY_PROFILER_LABEL
+#endif
+
+#define BEFORE_GL_CALL \
+ ANDROID_ONLY_PROFILER_LABEL \
+ if (MOZ_LIKELY(BeforeGLCall(MOZ_FUNCTION_NAME))) { \
+ do { \
+ } while (0)
+
+#define AFTER_GL_CALL \
+ AfterGLCall(MOZ_FUNCTION_NAME); \
+ } \
+ do { \
+ } while (0)
+
+ void BeforeGLCall_Debug(const char* funcName) const;
+ void AfterGLCall_Debug(const char* funcName) const;
+ static void OnImplicitMakeCurrentFailure(const char* funcName);
+
+ bool BeforeGLCall(const char* const funcName) const {
+ if (mImplicitMakeCurrent) {
+ if (MOZ_UNLIKELY(!MakeCurrent())) {
+ if (!mContextLost) {
+ OnImplicitMakeCurrentFailure(funcName);
+ }
+ return false;
+ }
+ }
+ MOZ_GL_ASSERT(this, IsCurrentImpl());
+
+ if (MOZ_UNLIKELY(mDebugFlags)) {
+ BeforeGLCall_Debug(funcName);
+ }
+ return true;
+ }
+
+ void AfterGLCall(const char* const funcName) const {
+ if (MOZ_UNLIKELY(mDebugFlags)) {
+ AfterGLCall_Debug(funcName);
+ }
+ }
+
+ GLContext* TrackingContext() {
+ GLContext* tip = this;
+ while (tip->mSharedContext) tip = tip->mSharedContext;
+ return tip;
+ }
+
+ static void AssertNotPassingStackBufferToTheGL(const void* ptr);
+
+#ifdef MOZ_GL_DEBUG_BUILD
+
+# define TRACKING_CONTEXT(a) \
+ do { \
+ TrackingContext()->a; \
+ } while (0)
+
+# define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) \
+ AssertNotPassingStackBufferToTheGL(ptr)
+
+# define ASSERT_SYMBOL_PRESENT(func) \
+ do { \
+ MOZ_ASSERT(strstr(MOZ_FUNCTION_NAME, #func) != nullptr, \
+ "Mismatched symbol check."); \
+ if (MOZ_UNLIKELY(!mSymbols.func)) { \
+ printf_stderr("RUNTIME ASSERT: Uninitialized GL function: %s\n", \
+ #func); \
+ MOZ_CRASH("GFX: Uninitialized GL function"); \
+ } \
+ } while (0)
+
+#else // ifdef MOZ_GL_DEBUG_BUILD
+
+# define TRACKING_CONTEXT(a) \
+ do { \
+ } while (0)
+# define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) \
+ do { \
+ } while (0)
+# define ASSERT_SYMBOL_PRESENT(func) \
+ do { \
+ } while (0)
+
+#endif // ifdef MOZ_GL_DEBUG_BUILD
+
+ // Do whatever setup is necessary to draw to our offscreen FBO, if it's
+ // bound.
+ void BeforeGLDrawCall() {}
+
+ // Do whatever tear-down is necessary after drawing to our offscreen FBO,
+ // if it's bound.
+ void AfterGLDrawCall() { mHeavyGLCallsSinceLastFlush = true; }
+
+ // Do whatever setup is necessary to read from our offscreen FBO, if it's
+ // bound.
+ void BeforeGLReadCall() {}
+
+ // Do whatever tear-down is necessary after reading from our offscreen FBO,
+ // if it's bound.
+ void AfterGLReadCall() {}
+
+ public:
+ void OnSyncCall() const { mSyncGLCallCount++; }
+
+ uint64_t GetSyncCallCount() const { return mSyncGLCallCount; }
+
+ void ResetSyncCallCount(const char* resetReason) const;
+
+ // -----------------------------------------------------------------------------
+ // GL official entry points
+ public:
+ // We smash all errors together, so you never have to loop on this. We
+ // guarantee that immediately after this call, there are no errors left.
+ // Always returns the top-most error, except if followed by CONTEXT_LOST, then
+ // return that instead.
+ GLenum GetError() const;
+
+ GLenum fGetError() { return GetError(); }
+
+ GLenum fGetGraphicsResetStatus() const;
+
+ // -
+
+ void fActiveTexture(GLenum texture) {
+ BEFORE_GL_CALL;
+ mSymbols.fActiveTexture(texture);
+ AFTER_GL_CALL;
+ }
+
+ void fAttachShader(GLuint program, GLuint shader) {
+ BEFORE_GL_CALL;
+ mSymbols.fAttachShader(program, shader);
+ AFTER_GL_CALL;
+ }
+
+ void fBeginQuery(GLenum target, GLuint id) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBeginQuery);
+ mSymbols.fBeginQuery(target, id);
+ AFTER_GL_CALL;
+ }
+
+ void fBindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
+ BEFORE_GL_CALL;
+ mSymbols.fBindAttribLocation(program, index, name);
+ AFTER_GL_CALL;
+ }
+
+ void fBindBuffer(GLenum target, GLuint buffer) {
+ BEFORE_GL_CALL;
+ mSymbols.fBindBuffer(target, buffer);
+ AFTER_GL_CALL;
+ }
+
+ void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
+ const GLenum* attachments) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
+ mSymbols.fInvalidateFramebuffer(target, numAttachments, attachments);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
+ const GLenum* attachments, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
+ mSymbols.fInvalidateSubFramebuffer(target, numAttachments, attachments, x,
+ y, width, height);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fBindTexture(GLenum target, GLuint texture) {
+ BEFORE_GL_CALL;
+ mSymbols.fBindTexture(target, texture);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendColor(red, green, blue, alpha);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendEquation(GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendEquation(mode);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendEquationSeparate(modeRGB, modeAlpha);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendFunc(GLenum sfactor, GLenum dfactor) {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendFunc(sfactor, dfactor);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorAlpha, GLenum dfactorAlpha) {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha,
+ dfactorAlpha);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ void raw_fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
+ GLenum usage) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(data);
+ BEFORE_GL_CALL;
+ mSymbols.fBufferData(target, size, data, usage);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ public:
+ void fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
+ GLenum usage) {
+ raw_fBufferData(target, size, data, usage);
+
+ // bug 744888
+ if (WorkAroundDriverBugs() && !data && Vendor() == GLVendor::NVIDIA) {
+ UniquePtr<char[]> buf = MakeUnique<char[]>(1);
+ buf[0] = 0;
+ fBufferSubData(target, size - 1, 1, buf.get());
+ }
+ }
+
+ void fBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+ const GLvoid* data) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(data);
+ BEFORE_GL_CALL;
+ mSymbols.fBufferSubData(target, offset, size, data);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ private:
+ void raw_fClear(GLbitfield mask) {
+ BEFORE_GL_CALL;
+ mSymbols.fClear(mask);
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fClear(GLbitfield mask) {
+ BeforeGLDrawCall();
+ raw_fClear(mask);
+ AfterGLDrawCall();
+ }
+
+ void fClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth,
+ GLint stencil) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ mSymbols.fClearBufferfi(buffer, drawbuffer, depth, stencil);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ mSymbols.fClearBufferfv(buffer, drawbuffer, value);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ mSymbols.fClearBufferiv(buffer, drawbuffer, value);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
+ BeforeGLDrawCall();
+ BEFORE_GL_CALL;
+ mSymbols.fClearBufferuiv(buffer, drawbuffer, value);
+ AFTER_GL_CALL;
+ AfterGLDrawCall();
+ }
+
+ void fClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
+ BEFORE_GL_CALL;
+ mSymbols.fClearColor(r, g, b, a);
+ AFTER_GL_CALL;
+ }
+
+ void fClearStencil(GLint s) {
+ BEFORE_GL_CALL;
+ mSymbols.fClearStencil(s);
+ AFTER_GL_CALL;
+ }
+
+ void fClientActiveTexture(GLenum texture) {
+ BEFORE_GL_CALL;
+ mSymbols.fClientActiveTexture(texture);
+ AFTER_GL_CALL;
+ }
+
+ void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue,
+ realGLboolean alpha) {
+ BEFORE_GL_CALL;
+ mSymbols.fColorMask(red, green, blue, alpha);
+ AFTER_GL_CALL;
+ }
+
+ void fCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid* pixels) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
+ BEFORE_GL_CALL;
+ mSymbols.fCompressedTexImage2D(target, level, internalformat, width, height,
+ border, imageSize, pixels);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ void fCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize,
+ const GLvoid* pixels) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
+ BEFORE_GL_CALL;
+ mSymbols.fCompressedTexSubImage2D(target, level, xoffset, yoffset, width,
+ height, format, imageSize, pixels);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border);
+
+ void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint x, GLint y, GLsizei width,
+ GLsizei height) {
+ BeforeGLReadCall();
+ raw_fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
+ height);
+ AfterGLReadCall();
+ }
+
+ void fCullFace(GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fCullFace(mode);
+ AFTER_GL_CALL;
+ }
+
+ void fDebugMessageCallback(GLDEBUGPROC callback, const GLvoid* userParam) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDebugMessageCallback);
+ mSymbols.fDebugMessageCallback(callback, userParam);
+ AFTER_GL_CALL;
+ }
+
+ void fDebugMessageControl(GLenum source, GLenum type, GLenum severity,
+ GLsizei count, const GLuint* ids,
+ realGLboolean enabled) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDebugMessageControl);
+ mSymbols.fDebugMessageControl(source, type, severity, count, ids, enabled);
+ AFTER_GL_CALL;
+ }
+
+ void fDebugMessageInsert(GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei length, const GLchar* buf) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDebugMessageInsert);
+ mSymbols.fDebugMessageInsert(source, type, id, severity, length, buf);
+ AFTER_GL_CALL;
+ }
+
+ void fDetachShader(GLuint program, GLuint shader) {
+ BEFORE_GL_CALL;
+ mSymbols.fDetachShader(program, shader);
+ AFTER_GL_CALL;
+ }
+
+ void fDepthFunc(GLenum func) {
+ BEFORE_GL_CALL;
+ mSymbols.fDepthFunc(func);
+ AFTER_GL_CALL;
+ }
+
+ void fDepthMask(realGLboolean flag) {
+ BEFORE_GL_CALL;
+ mSymbols.fDepthMask(flag);
+ AFTER_GL_CALL;
+ }
+
+ void fDisable(GLenum capability) {
+ BEFORE_GL_CALL;
+ mSymbols.fDisable(capability);
+ AFTER_GL_CALL;
+ }
+
+ void fDisableClientState(GLenum capability) {
+ BEFORE_GL_CALL;
+ mSymbols.fDisableClientState(capability);
+ AFTER_GL_CALL;
+ }
+
+ void fDisableVertexAttribArray(GLuint index) {
+ BEFORE_GL_CALL;
+ mSymbols.fDisableVertexAttribArray(index);
+ AFTER_GL_CALL;
+ }
+
+ void fDrawBuffer(GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fDrawBuffer(mode);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) {
+ BEFORE_GL_CALL;
+ mSymbols.fDrawArrays(mode, first, count);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices) {
+ BEFORE_GL_CALL;
+ mSymbols.fDrawElements(mode, count, type, indices);
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fDrawArrays(GLenum mode, GLint first, GLsizei count) {
+ BeforeGLDrawCall();
+ raw_fDrawArrays(mode, first, count);
+ AfterGLDrawCall();
+ }
+
+ void fDrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices) {
+ BeforeGLDrawCall();
+ raw_fDrawElements(mode, count, type, indices);
+ AfterGLDrawCall();
+ }
+
+ void fEnable(GLenum capability) {
+ BEFORE_GL_CALL;
+ mSymbols.fEnable(capability);
+ AFTER_GL_CALL;
+ }
+
+ void fEnableClientState(GLenum capability) {
+ BEFORE_GL_CALL;
+ mSymbols.fEnableClientState(capability);
+ AFTER_GL_CALL;
+ }
+
+ void fEnableVertexAttribArray(GLuint index) {
+ BEFORE_GL_CALL;
+ mSymbols.fEnableVertexAttribArray(index);
+ AFTER_GL_CALL;
+ }
+
+ void fEndQuery(GLenum target) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fEndQuery);
+ mSymbols.fEndQuery(target);
+ AFTER_GL_CALL;
+ }
+
+ void fFinish() {
+ BEFORE_GL_CALL;
+ mSymbols.fFinish();
+ OnSyncCall();
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = false;
+ }
+
+ void fFlush() {
+ BEFORE_GL_CALL;
+ mSymbols.fFlush();
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = false;
+ }
+
+ void fFrontFace(GLenum face) {
+ BEFORE_GL_CALL;
+ mSymbols.fFrontFace(face);
+ AFTER_GL_CALL;
+ }
+
+ void fGetActiveAttrib(GLuint program, GLuint index, GLsizei maxLength,
+ GLsizei* length, GLint* size, GLenum* type,
+ GLchar* name) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetActiveAttrib(program, index, maxLength, length, size, type,
+ name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetActiveUniform(GLuint program, GLuint index, GLsizei maxLength,
+ GLsizei* length, GLint* size, GLenum* type,
+ GLchar* name) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetActiveUniform(program, index, maxLength, length, size, type,
+ name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count,
+ GLuint* shaders) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ GLint fGetAttribLocation(GLuint program, const GLchar* name) {
+ GLint retval = 0;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fGetAttribLocation(program, name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ private:
+ void raw_fGetIntegerv(GLenum pname, GLint* params) const {
+ BEFORE_GL_CALL;
+ mSymbols.fGetIntegerv(pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fGetIntegerv(GLenum pname, GLint* params) const;
+
+ template <typename T>
+ void GetInt(const GLenum pname, T* const params) const {
+ static_assert(sizeof(T) == sizeof(GLint), "Invalid T.");
+ fGetIntegerv(pname, reinterpret_cast<GLint*>(params));
+ }
+
+ void GetUIntegerv(GLenum pname, GLuint* params) const {
+ GetInt(pname, params);
+ }
+
+ template <typename T>
+ T GetIntAs(GLenum pname) const {
+ static_assert(sizeof(T) == sizeof(GLint), "Invalid T.");
+ T ret = 0;
+ fGetIntegerv(pname, (GLint*)&ret);
+ return ret;
+ }
+
+ void fGetFloatv(GLenum pname, GLfloat* params) const {
+ BEFORE_GL_CALL;
+ mSymbols.fGetFloatv(pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetBooleanv(GLenum pname, realGLboolean* params) const {
+ BEFORE_GL_CALL;
+ mSymbols.fGetBooleanv(pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetBufferParameteriv(target, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ GLuint fGetDebugMessageLog(GLuint count, GLsizei bufsize, GLenum* sources,
+ GLenum* types, GLuint* ids, GLenum* severities,
+ GLsizei* lengths, GLchar* messageLog) {
+ GLuint ret = 0;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetDebugMessageLog);
+ ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids,
+ severities, lengths, messageLog);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void fGetPointerv(GLenum pname, GLvoid** params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetPointerv);
+ mSymbols.fGetPointerv(pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize,
+ GLsizei* length, GLchar* label) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetObjectLabel);
+ mSymbols.fGetObjectLabel(identifier, name, bufSize, length, label);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetObjectPtrLabel(const GLvoid* ptr, GLsizei bufSize, GLsizei* length,
+ GLchar* label) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetObjectPtrLabel);
+ mSymbols.fGetObjectPtrLabel(ptr, bufSize, length, label);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGenerateMipmap(GLenum target) {
+ BEFORE_GL_CALL;
+ mSymbols.fGenerateMipmap(target);
+ AFTER_GL_CALL;
+ }
+
+ void fGetProgramiv(GLuint program, GLenum pname, GLint* param) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetProgramiv(program, pname, param);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fTexParameteri(GLenum target, GLenum pname, GLint param) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexParameteri(target, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fTexParameteriv(GLenum target, GLenum pname, const GLint* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexParameteriv(target, pname, params);
+ AFTER_GL_CALL;
+ }
+
+ void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexParameterf(target, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ const GLubyte* fGetString(GLenum name) {
+ const GLubyte* result = nullptr;
+ BEFORE_GL_CALL;
+ result = mSymbols.fGetString(name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return result;
+ }
+
+ void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type,
+ GLvoid* img) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetTexImage);
+ mSymbols.fGetTexImage(target, level, format, type, img);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname,
+ GLint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetTexLevelParameteriv);
+ mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetTexParameterfv(target, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetTexParameteriv(target, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetUniformfv(GLuint program, GLint location, GLfloat* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetUniformfv(program, location, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetUniformiv(GLuint program, GLint location, GLint* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetUniformiv(program, location, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetUniformuiv(GLuint program, GLint location, GLuint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetUniformuiv);
+ mSymbols.fGetUniformuiv(program, location, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ GLint fGetUniformLocation(GLuint programObj, const GLchar* name) {
+ GLint retval = 0;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fGetUniformLocation(programObj, name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetVertexAttribfv(index, pname, retval);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetVertexAttribiv(index, pname, retval);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** retval) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetVertexAttribPointerv(index, pname, retval);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fHint(GLenum target, GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fHint(target, mode);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsBuffer(GLuint buffer) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsBuffer(buffer);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ realGLboolean fIsEnabled(GLenum capability) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsEnabled(capability);
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ void SetEnabled(const GLenum cap, const bool val) {
+ if (val) {
+ fEnable(cap);
+ } else {
+ fDisable(cap);
+ }
+ }
+
+ bool PushEnabled(const GLenum cap, const bool newVal) {
+ const bool oldVal = fIsEnabled(cap);
+ if (oldVal != newVal) {
+ SetEnabled(cap, newVal);
+ }
+ return oldVal;
+ }
+
+ realGLboolean fIsProgram(GLuint program) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsProgram(program);
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ realGLboolean fIsShader(GLuint shader) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsShader(shader);
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ realGLboolean fIsTexture(GLuint texture) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsTexture(texture);
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ void fLineWidth(GLfloat width) {
+ BEFORE_GL_CALL;
+ mSymbols.fLineWidth(width);
+ AFTER_GL_CALL;
+ }
+
+ void fLinkProgram(GLuint program) {
+ BEFORE_GL_CALL;
+ mSymbols.fLinkProgram(program);
+ AFTER_GL_CALL;
+ }
+
+ void fObjectLabel(GLenum identifier, GLuint name, GLsizei length,
+ const GLchar* label) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fObjectLabel);
+ mSymbols.fObjectLabel(identifier, name, length, label);
+ AFTER_GL_CALL;
+ }
+
+ void fObjectPtrLabel(const GLvoid* ptr, GLsizei length, const GLchar* label) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fObjectPtrLabel);
+ mSymbols.fObjectPtrLabel(ptr, length, label);
+ AFTER_GL_CALL;
+ }
+
+ void fLoadIdentity() {
+ BEFORE_GL_CALL;
+ mSymbols.fLoadIdentity();
+ AFTER_GL_CALL;
+ }
+
+ void fLoadMatrixf(const GLfloat* matrix) {
+ BEFORE_GL_CALL;
+ mSymbols.fLoadMatrixf(matrix);
+ AFTER_GL_CALL;
+ }
+
+ void fMatrixMode(GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fMatrixMode(mode);
+ AFTER_GL_CALL;
+ }
+
+ void fPixelStorei(GLenum pname, GLint param) {
+ BEFORE_GL_CALL;
+ mSymbols.fPixelStorei(pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid* pointer) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pointer);
+ BEFORE_GL_CALL;
+ mSymbols.fTextureRangeAPPLE(target, length, pointer);
+ AFTER_GL_CALL;
+ }
+
+ void fPointParameterf(GLenum pname, GLfloat param) {
+ BEFORE_GL_CALL;
+ mSymbols.fPointParameterf(pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fPolygonMode(GLenum face, GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fPolygonMode(face, mode);
+ AFTER_GL_CALL;
+ }
+
+ void fPolygonOffset(GLfloat factor, GLfloat bias) {
+ BEFORE_GL_CALL;
+ mSymbols.fPolygonOffset(factor, bias);
+ AFTER_GL_CALL;
+ }
+
+ void fPopDebugGroup() {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fPopDebugGroup);
+ mSymbols.fPopDebugGroup();
+ AFTER_GL_CALL;
+ }
+
+ void fPushDebugGroup(GLenum source, GLuint id, GLsizei length,
+ const GLchar* message) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fPushDebugGroup);
+ mSymbols.fPushDebugGroup(source, id, length, message);
+ AFTER_GL_CALL;
+ }
+
+ void fReadBuffer(GLenum mode) {
+ BEFORE_GL_CALL;
+ mSymbols.fReadBuffer(mode);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid* pixels) {
+ BEFORE_GL_CALL;
+ mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid* pixels);
+
+ public:
+ void fSampleCoverage(GLclampf value, realGLboolean invert) {
+ BEFORE_GL_CALL;
+ mSymbols.fSampleCoverage(value, invert);
+ AFTER_GL_CALL;
+ }
+
+ void fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+ if (mScissorRect[0] == x && mScissorRect[1] == y &&
+ mScissorRect[2] == width && mScissorRect[3] == height) {
+ return;
+ }
+ mScissorRect[0] = x;
+ mScissorRect[1] = y;
+ mScissorRect[2] = width;
+ mScissorRect[3] = height;
+ BEFORE_GL_CALL;
+ mSymbols.fScissor(x, y, width, height);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilFunc(GLenum func, GLint reference, GLuint mask) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilFunc(func, reference, mask);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint reference,
+ GLuint mask) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilFuncSeparate(frontfunc, backfunc, reference, mask);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilMask(GLuint mask) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilMask(mask);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilMaskSeparate(GLenum face, GLuint mask) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilMaskSeparate(face, mask);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilOp(fail, zfail, zpass);
+ AFTER_GL_CALL;
+ }
+
+ void fStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
+ GLenum dppass) {
+ BEFORE_GL_CALL;
+ mSymbols.fStencilOpSeparate(face, sfail, dpfail, dppass);
+ AFTER_GL_CALL;
+ }
+
+ void fTexGeni(GLenum coord, GLenum pname, GLint param) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexGeni(coord, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fTexGenf(GLenum coord, GLenum pname, GLfloat param) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexGenf(coord, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fTexGenfv(GLenum coord, GLenum pname, const GLfloat* params) {
+ BEFORE_GL_CALL;
+ mSymbols.fTexGenfv(coord, pname, params);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ void raw_fTexImage2D(GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const GLvoid* pixels) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
+ BEFORE_GL_CALL;
+ mSymbols.fTexImage2D(target, level, internalformat, width, height, border,
+ format, type, pixels);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ public:
+ void fTexImage2D(GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border, GLenum format,
+ GLenum type, const GLvoid* pixels);
+
+ void fTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const GLvoid* pixels) {
+ ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
+ BEFORE_GL_CALL;
+ mSymbols.fTexSubImage2D(target, level, xoffset, yoffset, width, height,
+ format, type, pixels);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ void fUniform1f(GLint location, GLfloat v0) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform1f(location, v0);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform1fv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform1i(GLint location, GLint v0) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform1i(location, v0);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform1iv(GLint location, GLsizei count, const GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform1iv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2f(GLint location, GLfloat v0, GLfloat v1) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform2f(location, v0, v1);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2fv(GLint location, GLsizei count, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform2fv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2i(GLint location, GLint v0, GLint v1) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform2i(location, v0, v1);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2iv(GLint location, GLsizei count, const GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform2iv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform3f(location, v0, v1, v2);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3fv(GLint location, GLsizei count, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform3fv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform3i(location, v0, v1, v2);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3iv(GLint location, GLsizei count, const GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform3iv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
+ GLfloat v3) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform4f(location, v0, v1, v2, v3);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform4fv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform4i(location, v0, v1, v2, v3);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4iv(GLint location, GLsizei count, const GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniform4iv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix2fv(GLint location, GLsizei count, realGLboolean transpose,
+ const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniformMatrix2fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix2x3fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix2x3fv);
+ mSymbols.fUniformMatrix2x3fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix2x4fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix2x4fv);
+ mSymbols.fUniformMatrix2x4fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix3fv(GLint location, GLsizei count, realGLboolean transpose,
+ const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniformMatrix3fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix3x2fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix3x2fv);
+ mSymbols.fUniformMatrix3x2fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix3x4fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix3x4fv);
+ mSymbols.fUniformMatrix3x4fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix4fv(GLint location, GLsizei count, realGLboolean transpose,
+ const GLfloat* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fUniformMatrix4fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix4x2fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix4x2fv);
+ mSymbols.fUniformMatrix4x2fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniformMatrix4x3fv(GLint location, GLsizei count,
+ realGLboolean transpose, const GLfloat* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniformMatrix4x3fv);
+ mSymbols.fUniformMatrix4x3fv(location, count, transpose, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUseProgram(GLuint program) {
+ BEFORE_GL_CALL;
+ mSymbols.fUseProgram(program);
+ AFTER_GL_CALL;
+ }
+
+ void fValidateProgram(GLuint program) {
+ BEFORE_GL_CALL;
+ mSymbols.fValidateProgram(program);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribPointer(GLuint index, GLint size, GLenum type,
+ realGLboolean normalized, GLsizei stride,
+ const GLvoid* pointer) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttribPointer(index, size, type, normalized, stride,
+ pointer);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib1f(GLuint index, GLfloat x) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib1f(index, x);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib2f(index, x, y);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib3f(index, x, y, z);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat w) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib4f(index, x, y, z, w);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib1fv(GLuint index, const GLfloat* v) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib1fv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib2fv(GLuint index, const GLfloat* v) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib2fv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib3fv(GLuint index, const GLfloat* v) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib3fv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttrib4fv(GLuint index, const GLfloat* v) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexAttrib4fv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexPointer(GLint size, GLenum type, GLsizei stride,
+ const GLvoid* pointer) {
+ BEFORE_GL_CALL;
+ mSymbols.fVertexPointer(size, type, stride, pointer);
+ AFTER_GL_CALL;
+ }
+
+ void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+ if (mViewportRect[0] == x && mViewportRect[1] == y &&
+ mViewportRect[2] == width && mViewportRect[3] == height) {
+ return;
+ }
+ mViewportRect[0] = x;
+ mViewportRect[1] = y;
+ mViewportRect[2] = width;
+ mViewportRect[3] = height;
+ BEFORE_GL_CALL;
+ mSymbols.fViewport(x, y, width, height);
+ AFTER_GL_CALL;
+ }
+
+ void fCompileShader(GLuint shader) {
+ BEFORE_GL_CALL;
+ mSymbols.fCompileShader(shader);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ friend class SharedSurface_IOSurface;
+
+ void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border) {
+ BEFORE_GL_CALL;
+ mSymbols.fCopyTexImage2D(target, level, internalformat, x, y, width, height,
+ border);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint x, GLint y, GLsizei width,
+ GLsizei height) {
+ BEFORE_GL_CALL;
+ mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
+ height);
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fGetShaderiv(GLuint shader, GLenum pname, GLint* param) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetShaderiv(shader, pname, param);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length,
+ GLchar* infoLog) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ private:
+ void raw_fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
+ GLint* range, GLint* precision) {
+ MOZ_ASSERT(IsGLES());
+
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetShaderPrecisionFormat);
+ mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range,
+ precision);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
+ GLint* range, GLint* precision) {
+ if (IsGLES()) {
+ raw_fGetShaderPrecisionFormat(shadertype, precisiontype, range,
+ precision);
+ } else {
+ // Fall back to automatic values because almost all desktop hardware
+ // supports the OpenGL standard precisions.
+ GetShaderPrecisionFormatNonES2(shadertype, precisiontype, range,
+ precision);
+ }
+ }
+
+ void fGetShaderSource(GLint obj, GLsizei maxLength, GLsizei* length,
+ GLchar* source) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetShaderSource(obj, maxLength, length, source);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fShaderSource(GLuint shader, GLsizei count, const GLchar* const* strings,
+ const GLint* lengths) {
+ BEFORE_GL_CALL;
+ mSymbols.fShaderSource(shader, count, strings, lengths);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ mutable GLuint mCachedDrawFb = 0;
+ mutable GLuint mCachedReadFb = 0;
+
+ public:
+ bool mElideDuplicateBindFramebuffers = false;
+
+ void fBindFramebuffer(const GLenum target, const GLuint fb) const {
+ if (mElideDuplicateBindFramebuffers) {
+ MOZ_ASSERT(mCachedDrawFb ==
+ GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING));
+ MOZ_ASSERT(mCachedReadFb ==
+ GetIntAs<GLuint>(LOCAL_GL_READ_FRAMEBUFFER_BINDING));
+
+ switch (target) {
+ case LOCAL_GL_FRAMEBUFFER:
+ if (mCachedDrawFb == fb && mCachedReadFb == fb) return;
+ break;
+ case LOCAL_GL_DRAW_FRAMEBUFFER:
+ if (mCachedDrawFb == fb) return;
+ break;
+ case LOCAL_GL_READ_FRAMEBUFFER:
+ if (mCachedReadFb == fb) return;
+ break;
+ }
+ }
+
+ BEFORE_GL_CALL;
+ mSymbols.fBindFramebuffer(target, fb);
+ AFTER_GL_CALL;
+
+ switch (target) {
+ case LOCAL_GL_FRAMEBUFFER:
+ mCachedDrawFb = fb;
+ mCachedReadFb = fb;
+ break;
+ case LOCAL_GL_DRAW_FRAMEBUFFER:
+ mCachedDrawFb = fb;
+ break;
+ case LOCAL_GL_READ_FRAMEBUFFER:
+ mCachedReadFb = fb;
+ break;
+ }
+ }
+
+ void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
+ BEFORE_GL_CALL;
+ mSymbols.fBindRenderbuffer(target, renderbuffer);
+ AFTER_GL_CALL;
+ }
+
+ GLenum fCheckFramebufferStatus(GLenum target) {
+ GLenum retval = 0;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fCheckFramebufferStatus(target);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint,
+ GLenum renderbufferTarget,
+ GLuint renderbuffer) {
+ BEFORE_GL_CALL;
+ mSymbols.fFramebufferRenderbuffer(target, attachmentPoint,
+ renderbufferTarget, renderbuffer);
+ AFTER_GL_CALL;
+ }
+
+ void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint,
+ GLenum textureTarget, GLuint texture,
+ GLint level) {
+ BEFORE_GL_CALL;
+ mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget,
+ texture, level);
+ AFTER_GL_CALL;
+ }
+
+ void fFramebufferTextureLayer(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fFramebufferTextureLayer);
+ mSymbols.fFramebufferTextureLayer(target, attachment, texture, level,
+ layer);
+ AFTER_GL_CALL;
+ }
+
+ void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
+ GLenum pname, GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname,
+ value);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
+ BEFORE_GL_CALL;
+ mSymbols.fGetRenderbufferParameteriv(target, pname, value);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsFramebuffer(GLuint framebuffer) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsFramebuffer(framebuffer);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ public:
+ realGLboolean fIsRenderbuffer(GLuint renderbuffer) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ retval = mSymbols.fIsRenderbuffer(renderbuffer);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width,
+ GLsizei height) {
+ BEFORE_GL_CALL;
+ mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
+ AFTER_GL_CALL;
+ }
+
+ private:
+ void raw_fDepthRange(GLclampf a, GLclampf b) {
+ MOZ_ASSERT(!IsGLES());
+
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDepthRange);
+ mSymbols.fDepthRange(a, b);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDepthRangef(GLclampf a, GLclampf b) {
+ MOZ_ASSERT(IsGLES());
+
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDepthRangef);
+ mSymbols.fDepthRangef(a, b);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fClearDepth(GLclampf v) {
+ MOZ_ASSERT(!IsGLES());
+
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fClearDepth);
+ mSymbols.fClearDepth(v);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fClearDepthf(GLclampf v) {
+ MOZ_ASSERT(IsGLES());
+
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fClearDepthf);
+ mSymbols.fClearDepthf(v);
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fDepthRange(GLclampf a, GLclampf b) {
+ if (IsGLES()) {
+ raw_fDepthRangef(a, b);
+ } else {
+ raw_fDepthRange(a, b);
+ }
+ }
+
+ void fClearDepth(GLclampf v) {
+ if (IsGLES()) {
+ raw_fClearDepthf(v);
+ } else {
+ raw_fClearDepth(v);
+ }
+ }
+
+ void* fMapBuffer(GLenum target, GLenum access) {
+ void* ret = nullptr;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fMapBuffer);
+ ret = mSymbols.fMapBuffer(target, access);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ realGLboolean fUnmapBuffer(GLenum target) {
+ realGLboolean ret = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
+ ret = mSymbols.fUnmapBuffer(target);
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ private:
+ GLuint raw_fCreateProgram() {
+ GLuint ret = 0;
+ BEFORE_GL_CALL;
+ ret = mSymbols.fCreateProgram();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ GLuint raw_fCreateShader(GLenum t) {
+ GLuint ret = 0;
+ BEFORE_GL_CALL;
+ ret = mSymbols.fCreateShader(t);
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void raw_fGenBuffers(GLsizei n, GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fGenBuffers(n, names);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void raw_fGenFramebuffers(GLsizei n, GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fGenFramebuffers(n, names);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void raw_fGenRenderbuffers(GLsizei n, GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fGenRenderbuffers(n, names);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void raw_fGenTextures(GLsizei n, GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fGenTextures(n, names);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ public:
+ GLuint fCreateProgram() {
+ GLuint ret = raw_fCreateProgram();
+ TRACKING_CONTEXT(CreatedProgram(this, ret));
+ return ret;
+ }
+
+ GLuint fCreateShader(GLenum t) {
+ GLuint ret = raw_fCreateShader(t);
+ TRACKING_CONTEXT(CreatedShader(this, ret));
+ return ret;
+ }
+
+ void fGenBuffers(GLsizei n, GLuint* names) {
+ raw_fGenBuffers(n, names);
+ TRACKING_CONTEXT(CreatedBuffers(this, n, names));
+ }
+
+ void fGenFramebuffers(GLsizei n, GLuint* names) {
+ raw_fGenFramebuffers(n, names);
+ TRACKING_CONTEXT(CreatedFramebuffers(this, n, names));
+ }
+
+ void fGenRenderbuffers(GLsizei n, GLuint* names) {
+ raw_fGenRenderbuffers(n, names);
+ TRACKING_CONTEXT(CreatedRenderbuffers(this, n, names));
+ }
+
+ void fGenTextures(GLsizei n, GLuint* names) {
+ raw_fGenTextures(n, names);
+ TRACKING_CONTEXT(CreatedTextures(this, n, names));
+ }
+
+ private:
+ void raw_fDeleteProgram(GLuint program) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteProgram(program);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDeleteShader(GLuint shader) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteShader(shader);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDeleteBuffers(GLsizei n, const GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteBuffers(n, names);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDeleteFramebuffers(GLsizei n, const GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteFramebuffers(n, names);
+ AFTER_GL_CALL;
+
+ for (const auto i : IntegerRange(n)) {
+ const auto fb = names[i];
+ if (mCachedDrawFb == fb) {
+ mCachedDrawFb = 0;
+ }
+ if (mCachedReadFb == fb) {
+ mCachedReadFb = 0;
+ }
+ }
+ }
+
+ void raw_fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteRenderbuffers(n, names);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDeleteTextures(GLsizei n, const GLuint* names) {
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteTextures(n, names);
+ AFTER_GL_CALL;
+ }
+
+ public:
+ void fDeleteProgram(GLuint program) {
+ raw_fDeleteProgram(program);
+ TRACKING_CONTEXT(DeletedProgram(this, program));
+ }
+
+ void fDeleteShader(GLuint shader) {
+ raw_fDeleteShader(shader);
+ TRACKING_CONTEXT(DeletedShader(this, shader));
+ }
+
+ void fDeleteBuffers(GLsizei n, const GLuint* names) {
+ raw_fDeleteBuffers(n, names);
+ TRACKING_CONTEXT(DeletedBuffers(this, n, names));
+ }
+
+ void fDeleteFramebuffers(GLsizei n, const GLuint* names);
+
+ void fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
+ raw_fDeleteRenderbuffers(n, names);
+ TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
+ }
+
+ void fDeleteTextures(GLsizei n, const GLuint* names) {
+#ifdef XP_MACOSX
+ // On the Mac the call to fDeleteTextures() triggers a flush. But it
+ // happens at the wrong time, which can lead to crashes. To work around
+ // this we call fFlush() explicitly ourselves, before the call to
+ // fDeleteTextures(). This fixes bug 1666293.
+ fFlush();
+#endif
+ raw_fDeleteTextures(n, names);
+ TRACKING_CONTEXT(DeletedTextures(this, n, names));
+ }
+
+ // -----------------------------------------------------------------------------
+ // Extension ARB_sync (GL)
+ public:
+ GLsync fFenceSync(GLenum condition, GLbitfield flags) {
+ GLsync ret = 0;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fFenceSync);
+ ret = mSymbols.fFenceSync(condition, flags);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ realGLboolean fIsSync(GLsync sync) {
+ realGLboolean ret = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fIsSync);
+ ret = mSymbols.fIsSync(sync);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void fDeleteSync(GLsync sync) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDeleteSync);
+ mSymbols.fDeleteSync(sync);
+ AFTER_GL_CALL;
+ }
+
+ GLenum fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ GLenum ret = 0;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fClientWaitSync);
+ ret = mSymbols.fClientWaitSync(sync, flags, timeout);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fWaitSync);
+ mSymbols.fWaitSync(sync, flags, timeout);
+ AFTER_GL_CALL;
+ }
+
+ void fGetInteger64v(GLenum pname, GLint64* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetInteger64v);
+ mSymbols.fGetInteger64v(pname, params);
+ AFTER_GL_CALL;
+ }
+
+ void fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length,
+ GLint* values) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetSynciv);
+ mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Extension OES_EGL_image (GLES)
+ public:
+ void fEGLImageTargetTexture2D(GLenum target, GLeglImage image) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fEGLImageTargetTexture2D);
+ mSymbols.fEGLImageTargetTexture2D(target, image);
+ AFTER_GL_CALL;
+ mHeavyGLCallsSinceLastFlush = true;
+ }
+
+ void fEGLImageTargetRenderbufferStorage(GLenum target, GLeglImage image) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fEGLImageTargetRenderbufferStorage);
+ mSymbols.fEGLImageTargetRenderbufferStorage(target, image);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_bind_buffer_offset
+ public:
+ void fBindBufferOffset(GLenum target, GLuint index, GLuint buffer,
+ GLintptr offset) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindBufferOffset);
+ mSymbols.fBindBufferOffset(target, index, buffer, offset);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_draw_buffers
+ public:
+ void fDrawBuffers(GLsizei n, const GLenum* bufs) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDrawBuffers);
+ mSymbols.fDrawBuffers(n, bufs);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_draw_instanced
+ public:
+ void fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+ GLsizei primcount) {
+ BeforeGLDrawCall();
+ raw_fDrawArraysInstanced(mode, first, count, primcount);
+ AfterGLDrawCall();
+ }
+
+ void fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices, GLsizei primcount) {
+ BeforeGLDrawCall();
+ raw_fDrawElementsInstanced(mode, count, type, indices, primcount);
+ AfterGLDrawCall();
+ }
+
+ private:
+ void raw_fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
+ GLsizei primcount) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDrawArraysInstanced);
+ mSymbols.fDrawArraysInstanced(mode, first, count, primcount);
+ AFTER_GL_CALL;
+ }
+
+ void raw_fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid* indices, GLsizei primcount) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDrawElementsInstanced);
+ mSymbols.fDrawElementsInstanced(mode, count, type, indices, primcount);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_framebuffer_blit
+ public:
+ // Draw/Read
+ void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) {
+ BeforeGLDrawCall();
+ BeforeGLReadCall();
+ raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+ AfterGLReadCall();
+ AfterGLDrawCall();
+ }
+
+ private:
+ void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBlitFramebuffer);
+ mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
+ dstY1, mask, filter);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_framebuffer_multisample
+ public:
+ void fRenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat, GLsizei width,
+ GLsizei height) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fRenderbufferStorageMultisample);
+ mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat,
+ width, height);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // GL 3.0, GL ES 3.0 & EXT_gpu_shader4
+ public:
+ void fGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) {
+ ASSERT_SYMBOL_PRESENT(fGetVertexAttribIiv);
+ BEFORE_GL_CALL;
+ mSymbols.fGetVertexAttribIiv(index, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) {
+ ASSERT_SYMBOL_PRESENT(fGetVertexAttribIuiv);
+ BEFORE_GL_CALL;
+ mSymbols.fGetVertexAttribIuiv(index, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribI4i);
+ mSymbols.fVertexAttribI4i(index, x, y, z, w);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribI4iv(GLuint index, const GLint* v) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribI4iv);
+ mSymbols.fVertexAttribI4iv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribI4ui);
+ mSymbols.fVertexAttribI4ui(index, x, y, z, w);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribI4uiv(GLuint index, const GLuint* v) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribI4uiv);
+ mSymbols.fVertexAttribI4uiv(index, v);
+ AFTER_GL_CALL;
+ }
+
+ void fVertexAttribIPointer(GLuint index, GLint size, GLenum type,
+ GLsizei stride, const GLvoid* offset) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribIPointer);
+ mSymbols.fVertexAttribIPointer(index, size, type, stride, offset);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform1ui(GLint location, GLuint v0) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform1ui);
+ mSymbols.fUniform1ui(location, v0);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2ui(GLint location, GLuint v0, GLuint v1) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform2ui);
+ mSymbols.fUniform2ui(location, v0, v1);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform3ui);
+ mSymbols.fUniform3ui(location, v0, v1, v2);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform4ui);
+ mSymbols.fUniform4ui(location, v0, v1, v2, v3);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform1uiv(GLint location, GLsizei count, const GLuint* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform1uiv);
+ mSymbols.fUniform1uiv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform2uiv(GLint location, GLsizei count, const GLuint* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform2uiv);
+ mSymbols.fUniform2uiv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform3uiv(GLint location, GLsizei count, const GLuint* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform3uiv);
+ mSymbols.fUniform3uiv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ void fUniform4uiv(GLint location, GLsizei count, const GLuint* value) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fUniform4uiv);
+ mSymbols.fUniform4uiv(location, count, value);
+ AFTER_GL_CALL;
+ }
+
+ GLint fGetFragDataLocation(GLuint program, const GLchar* name) {
+ GLint result = 0;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetFragDataLocation);
+ result = mSymbols.fGetFragDataLocation(program, name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return result;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_instanced_arrays
+ public:
+ void fVertexAttribDivisor(GLuint index, GLuint divisor) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fVertexAttribDivisor);
+ mSymbols.fVertexAttribDivisor(index, divisor);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Feature internalformat_query
+ public:
+ void fGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
+ GLsizei bufSize, GLint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetInternalformativ);
+ mSymbols.fGetInternalformativ(target, internalformat, pname, bufSize,
+ params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_query_counter
+ /**
+ * XXX_query_counter:
+ * - depends on XXX_query_objects
+ * - provide all followed entry points
+ * - provide GL_TIMESTAMP
+ */
+ public:
+ void fQueryCounter(GLuint id, GLenum target) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fQueryCounter);
+ mSymbols.fQueryCounter(id, target);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_query_objects
+ /**
+ * XXX_query_objects:
+ * - provide all followed entry points
+ *
+ * XXX_occlusion_query2:
+ * - depends on XXX_query_objects
+ * - provide ANY_SAMPLES_PASSED
+ *
+ * XXX_occlusion_query_boolean:
+ * - depends on XXX_occlusion_query2
+ * - provide ANY_SAMPLES_PASSED_CONSERVATIVE
+ */
+ public:
+ void fDeleteQueries(GLsizei n, const GLuint* names) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDeleteQueries);
+ mSymbols.fDeleteQueries(n, names);
+ AFTER_GL_CALL;
+ TRACKING_CONTEXT(DeletedQueries(this, n, names));
+ }
+
+ void fGenQueries(GLsizei n, GLuint* names) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGenQueries);
+ mSymbols.fGenQueries(n, names);
+ AFTER_GL_CALL;
+ TRACKING_CONTEXT(CreatedQueries(this, n, names));
+ }
+
+ void fGetQueryiv(GLenum target, GLenum pname, GLint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetQueryiv);
+ mSymbols.fGetQueryiv(target, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetQueryObjectuiv);
+ mSymbols.fGetQueryObjectuiv(id, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsQuery(GLuint query) {
+ realGLboolean retval = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fIsQuery);
+ retval = mSymbols.fIsQuery(query);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return retval;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_get_query_object_i64v
+ /**
+ * XXX_get_query_object_i64v:
+ * - depends on XXX_query_objects
+ * - provide the followed entry point
+ */
+ public:
+ void fGetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetQueryObjecti64v);
+ mSymbols.fGetQueryObjecti64v(id, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetQueryObjectui64v);
+ mSymbols.fGetQueryObjectui64v(id, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_get_query_object_iv
+ /**
+ * XXX_get_query_object_iv:
+ * - depends on XXX_query_objects
+ * - provide the followed entry point
+ *
+ * XXX_occlusion_query:
+ * - depends on XXX_get_query_object_iv
+ * - provide LOCAL_GL_SAMPLES_PASSED
+ */
+ public:
+ void fGetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetQueryObjectiv);
+ mSymbols.fGetQueryObjectiv(id, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // GL 4.0, GL ES 3.0, ARB_transform_feedback2, NV_transform_feedback2
+ public:
+ void fBindBufferBase(GLenum target, GLuint index, GLuint buffer) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindBufferBase);
+ mSymbols.fBindBufferBase(target, index, buffer);
+ AFTER_GL_CALL;
+ }
+
+ void fBindBufferRange(GLenum target, GLuint index, GLuint buffer,
+ GLintptr offset, GLsizeiptr size) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindBufferRange);
+ mSymbols.fBindBufferRange(target, index, buffer, offset, size);
+ AFTER_GL_CALL;
+ }
+
+ void fGenTransformFeedbacks(GLsizei n, GLuint* ids) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGenTransformFeedbacks);
+ mSymbols.fGenTransformFeedbacks(n, ids);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDeleteTransformFeedbacks);
+ mSymbols.fDeleteTransformFeedbacks(n, ids);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsTransformFeedback(GLuint id) {
+ realGLboolean result = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fIsTransformFeedback);
+ result = mSymbols.fIsTransformFeedback(id);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return result;
+ }
+
+ void fBindTransformFeedback(GLenum target, GLuint id) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindTransformFeedback);
+ mSymbols.fBindTransformFeedback(target, id);
+ AFTER_GL_CALL;
+ }
+
+ void fBeginTransformFeedback(GLenum primitiveMode) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBeginTransformFeedback);
+ mSymbols.fBeginTransformFeedback(primitiveMode);
+ AFTER_GL_CALL;
+ }
+
+ void fEndTransformFeedback() {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fEndTransformFeedback);
+ mSymbols.fEndTransformFeedback();
+ AFTER_GL_CALL;
+ }
+
+ void fTransformFeedbackVaryings(GLuint program, GLsizei count,
+ const GLchar* const* varyings,
+ GLenum bufferMode) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTransformFeedbackVaryings);
+ mSymbols.fTransformFeedbackVaryings(program, count, varyings, bufferMode);
+ AFTER_GL_CALL;
+ }
+
+ void fGetTransformFeedbackVarying(GLuint program, GLuint index,
+ GLsizei bufSize, GLsizei* length,
+ GLsizei* size, GLenum* type, GLchar* name) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetTransformFeedbackVarying);
+ mSymbols.fGetTransformFeedbackVarying(program, index, bufSize, length, size,
+ type, name);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fPauseTransformFeedback() {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fPauseTransformFeedback);
+ mSymbols.fPauseTransformFeedback();
+ AFTER_GL_CALL;
+ }
+
+ void fResumeTransformFeedback() {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fResumeTransformFeedback);
+ mSymbols.fResumeTransformFeedback();
+ AFTER_GL_CALL;
+ }
+
+ void fGetIntegeri_v(GLenum param, GLuint index, GLint* values) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetIntegeri_v);
+ mSymbols.fGetIntegeri_v(param, index, values);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetInteger64i_v(GLenum target, GLuint index, GLint64* data) {
+ ASSERT_SYMBOL_PRESENT(fGetInteger64i_v);
+ BEFORE_GL_CALL;
+ mSymbols.fGetInteger64i_v(target, index, data);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Package XXX_vertex_array_object
+ public:
+ void fBindVertexArray(GLuint array) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindVertexArray);
+ mSymbols.fBindVertexArray(array);
+ AFTER_GL_CALL;
+ }
+
+ void fDeleteVertexArrays(GLsizei n, const GLuint* arrays) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDeleteVertexArrays);
+ mSymbols.fDeleteVertexArrays(n, arrays);
+ AFTER_GL_CALL;
+ }
+
+ void fGenVertexArrays(GLsizei n, GLuint* arrays) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGenVertexArrays);
+ mSymbols.fGenVertexArrays(n, arrays);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsVertexArray(GLuint array) {
+ realGLboolean ret = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fIsVertexArray);
+ ret = mSymbols.fIsVertexArray(array);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Extension NV_fence
+ public:
+ void fGenFences(GLsizei n, GLuint* fences) {
+ ASSERT_SYMBOL_PRESENT(fGenFences);
+ BEFORE_GL_CALL;
+ mSymbols.fGenFences(n, fences);
+ AFTER_GL_CALL;
+ }
+
+ void fDeleteFences(GLsizei n, const GLuint* fences) {
+ ASSERT_SYMBOL_PRESENT(fDeleteFences);
+ BEFORE_GL_CALL;
+ mSymbols.fDeleteFences(n, fences);
+ AFTER_GL_CALL;
+ }
+
+ void fSetFence(GLuint fence, GLenum condition) {
+ ASSERT_SYMBOL_PRESENT(fSetFence);
+ BEFORE_GL_CALL;
+ mSymbols.fSetFence(fence, condition);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fTestFence(GLuint fence) {
+ realGLboolean ret = false;
+ ASSERT_SYMBOL_PRESENT(fTestFence);
+ BEFORE_GL_CALL;
+ ret = mSymbols.fTestFence(fence);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void fFinishFence(GLuint fence) {
+ ASSERT_SYMBOL_PRESENT(fFinishFence);
+ BEFORE_GL_CALL;
+ mSymbols.fFinishFence(fence);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsFence(GLuint fence) {
+ realGLboolean ret = false;
+ ASSERT_SYMBOL_PRESENT(fIsFence);
+ BEFORE_GL_CALL;
+ ret = mSymbols.fIsFence(fence);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ void fGetFenceiv(GLuint fence, GLenum pname, GLint* params) {
+ ASSERT_SYMBOL_PRESENT(fGetFenceiv);
+ BEFORE_GL_CALL;
+ mSymbols.fGetFenceiv(fence, pname, params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Extension NV_texture_barrier
+ public:
+ void fTextureBarrier() {
+ ASSERT_SYMBOL_PRESENT(fTextureBarrier);
+ BEFORE_GL_CALL;
+ mSymbols.fTextureBarrier();
+ AFTER_GL_CALL;
+ }
+
+ // Core GL & Extension ARB_copy_buffer
+ public:
+ void fCopyBufferSubData(GLenum readtarget, GLenum writetarget,
+ GLintptr readoffset, GLintptr writeoffset,
+ GLsizeiptr size) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fCopyBufferSubData);
+ mSymbols.fCopyBufferSubData(readtarget, writetarget, readoffset,
+ writeoffset, size);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Core GL & Extension ARB_map_buffer_range
+ public:
+ void* fMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
+ GLbitfield access) {
+ void* data = nullptr;
+ ASSERT_SYMBOL_PRESENT(fMapBufferRange);
+ BEFORE_GL_CALL;
+ data = mSymbols.fMapBufferRange(target, offset, length, access);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return data;
+ }
+
+ void fFlushMappedBufferRange(GLenum target, GLintptr offset,
+ GLsizeiptr length) {
+ ASSERT_SYMBOL_PRESENT(fFlushMappedBufferRange);
+ BEFORE_GL_CALL;
+ mSymbols.fFlushMappedBufferRange(target, offset, length);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Core GL & Extension ARB_sampler_objects
+ public:
+ void fGenSamplers(GLsizei count, GLuint* samplers) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGenSamplers);
+ mSymbols.fGenSamplers(count, samplers);
+ AFTER_GL_CALL;
+ }
+
+ void fDeleteSamplers(GLsizei count, const GLuint* samplers) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fDeleteSamplers);
+ mSymbols.fDeleteSamplers(count, samplers);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fIsSampler(GLuint sampler) {
+ realGLboolean result = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fIsSampler);
+ result = mSymbols.fIsSampler(sampler);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return result;
+ }
+
+ void fBindSampler(GLuint unit, GLuint sampler) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fBindSampler);
+ mSymbols.fBindSampler(unit, sampler);
+ AFTER_GL_CALL;
+ }
+
+ void fSamplerParameteri(GLuint sampler, GLenum pname, GLint param) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fSamplerParameteri);
+ mSymbols.fSamplerParameteri(sampler, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fSamplerParameteriv);
+ mSymbols.fSamplerParameteriv(sampler, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fSamplerParameterf);
+ mSymbols.fSamplerParameterf(sampler, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fSamplerParameterfv);
+ mSymbols.fSamplerParameterfv(sampler, pname, param);
+ AFTER_GL_CALL;
+ }
+
+ void fGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetSamplerParameteriv);
+ mSymbols.fGetSamplerParameteriv(sampler, pname, params);
+ AFTER_GL_CALL;
+ }
+
+ void fGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetSamplerParameterfv);
+ mSymbols.fGetSamplerParameterfv(sampler, pname, params);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Core GL & Extension ARB_uniform_buffer_object
+ public:
+ void fGetUniformIndices(GLuint program, GLsizei uniformCount,
+ const GLchar* const* uniformNames,
+ GLuint* uniformIndices) {
+ ASSERT_SYMBOL_PRESENT(fGetUniformIndices);
+ BEFORE_GL_CALL;
+ mSymbols.fGetUniformIndices(program, uniformCount, uniformNames,
+ uniformIndices);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetActiveUniformsiv(GLuint program, GLsizei uniformCount,
+ const GLuint* uniformIndices, GLenum pname,
+ GLint* params) {
+ ASSERT_SYMBOL_PRESENT(fGetActiveUniformsiv);
+ BEFORE_GL_CALL;
+ mSymbols.fGetActiveUniformsiv(program, uniformCount, uniformIndices, pname,
+ params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ GLuint fGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) {
+ GLuint result = 0;
+ ASSERT_SYMBOL_PRESENT(fGetUniformBlockIndex);
+ BEFORE_GL_CALL;
+ result = mSymbols.fGetUniformBlockIndex(program, uniformBlockName);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return result;
+ }
+
+ void fGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex,
+ GLenum pname, GLint* params) {
+ ASSERT_SYMBOL_PRESENT(fGetActiveUniformBlockiv);
+ BEFORE_GL_CALL;
+ mSymbols.fGetActiveUniformBlockiv(program, uniformBlockIndex, pname,
+ params);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex,
+ GLsizei bufSize, GLsizei* length,
+ GLchar* uniformBlockName) {
+ ASSERT_SYMBOL_PRESENT(fGetActiveUniformBlockName);
+ BEFORE_GL_CALL;
+ mSymbols.fGetActiveUniformBlockName(program, uniformBlockIndex, bufSize,
+ length, uniformBlockName);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fUniformBlockBinding(GLuint program, GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding) {
+ ASSERT_SYMBOL_PRESENT(fUniformBlockBinding);
+ BEFORE_GL_CALL;
+ mSymbols.fUniformBlockBinding(program, uniformBlockIndex,
+ uniformBlockBinding);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // Core GL 4.2, GL ES 3.0 & Extension ARB_texture_storage/EXT_texture_storage
+ void fTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTexStorage2D);
+ mSymbols.fTexStorage2D(target, levels, internalformat, width, height);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTexStorage3D);
+ mSymbols.fTexStorage3D(target, levels, internalformat, width, height,
+ depth);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // 3D Textures
+ void fTexImage3D(GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border,
+ GLenum format, GLenum type, const GLvoid* data) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTexImage3D);
+ mSymbols.fTexImage3D(target, level, internalFormat, width, height, depth,
+ border, format, type, data);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLint zoffset, GLsizei width, GLsizei height,
+ GLsizei depth, GLenum format, GLenum type,
+ const GLvoid* pixels) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTexSubImage3D);
+ mSymbols.fTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
+ height, depth, format, type, pixels);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ }
+
+ void fCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLint x, GLint y,
+ GLsizei width, GLsizei height) {
+ BeforeGLReadCall();
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fCopyTexSubImage3D);
+ mSymbols.fCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y,
+ width, height);
+ AFTER_GL_CALL;
+ AfterGLReadCall();
+ }
+
+ void fCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLsizei imageSize,
+ const GLvoid* data) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fCompressedTexImage3D);
+ mSymbols.fCompressedTexImage3D(target, level, internalformat, width, height,
+ depth, border, imageSize, data);
+ AFTER_GL_CALL;
+ }
+
+ void fCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLint zoffset, GLsizei width,
+ GLsizei height, GLsizei depth, GLenum format,
+ GLsizei imageSize, const GLvoid* data) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fCompressedTexSubImage3D);
+ mSymbols.fCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, imageSize,
+ data);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // GL3+, ES3+
+
+ const GLubyte* fGetStringi(GLenum name, GLuint index) {
+ const GLubyte* ret = nullptr;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fGetStringi);
+ ret = mSymbols.fGetStringi(name, index);
+ OnSyncCall();
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ // -----------------------------------------------------------------------------
+ // APPLE_framebuffer_multisample
+
+ void fResolveMultisampleFramebufferAPPLE() {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fResolveMultisampleFramebufferAPPLE);
+ mSymbols.fResolveMultisampleFramebufferAPPLE();
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // APPLE_fence
+
+ void fFinishObjectAPPLE(GLenum object, GLint name) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fFinishObjectAPPLE);
+ mSymbols.fFinishObjectAPPLE(object, name);
+ AFTER_GL_CALL;
+ }
+
+ realGLboolean fTestObjectAPPLE(GLenum object, GLint name) {
+ realGLboolean ret = false;
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fTestObjectAPPLE);
+ ret = mSymbols.fTestObjectAPPLE(object, name);
+ AFTER_GL_CALL;
+ return ret;
+ }
+
+ // -----------------------------------------------------------------------------
+ // prim_restart
+
+ void fPrimitiveRestartIndex(GLuint index) {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fPrimitiveRestartIndex);
+ mSymbols.fPrimitiveRestartIndex(index);
+ AFTER_GL_CALL;
+ }
+
+ // -----------------------------------------------------------------------------
+ // multiview
+
+ void fFramebufferTextureMultiview(GLenum target, GLenum attachment,
+ GLuint texture, GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews) const {
+ BEFORE_GL_CALL;
+ ASSERT_SYMBOL_PRESENT(fFramebufferTextureMultiview);
+ mSymbols.fFramebufferTextureMultiview(target, attachment, texture, level,
+ baseViewIndex, numViews);
+ AFTER_GL_CALL;
+ }
+
+ // -
+ // draw_buffers_indexed
+
+ void fBlendEquationSeparatei(GLuint i, GLenum modeRGB,
+ GLenum modeAlpha) const {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendEquationSeparatei(i, modeRGB, modeAlpha);
+ AFTER_GL_CALL;
+ }
+
+ void fBlendFuncSeparatei(GLuint i, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorAlpha, GLenum dfactorAlpha) const {
+ BEFORE_GL_CALL;
+ mSymbols.fBlendFuncSeparatei(i, sfactorRGB, dfactorRGB, sfactorAlpha,
+ dfactorAlpha);
+ AFTER_GL_CALL;
+ }
+
+ void fColorMaski(GLuint i, realGLboolean red, realGLboolean green,
+ realGLboolean blue, realGLboolean alpha) const {
+ BEFORE_GL_CALL;
+ mSymbols.fColorMaski(i, red, green, blue, alpha);
+ AFTER_GL_CALL;
+ }
+
+ void fDisablei(GLenum capability, GLuint i) const {
+ BEFORE_GL_CALL;
+ mSymbols.fDisablei(capability, i);
+ AFTER_GL_CALL;
+ }
+
+ void fEnablei(GLenum capability, GLuint i) const {
+ BEFORE_GL_CALL;
+ mSymbols.fEnablei(capability, i);
+ AFTER_GL_CALL;
+ }
+
+ // -
+
+ void fProvokingVertex(GLenum mode) const {
+ BEFORE_GL_CALL;
+ mSymbols.fProvokingVertex(mode);
+ AFTER_GL_CALL;
+ }
+
+ // -
+
+#undef BEFORE_GL_CALL
+#undef AFTER_GL_CALL
+#undef ASSERT_SYMBOL_PRESENT
+// #undef TRACKING_CONTEXT // Needed in GLContext.cpp
+#undef ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL
+
+ // -----------------------------------------------------------------------------
+ // Constructor
+ protected:
+ explicit GLContext(const GLContextDesc&, GLContext* sharedContext = nullptr,
+ bool canUseTLSIsCurrent = false);
+
+ // -----------------------------------------------------------------------------
+ // Destructor
+ public:
+ virtual ~GLContext();
+
+ // Mark this context as destroyed. This will nullptr out all
+ // the GL function pointers!
+ void MarkDestroyed();
+
+ protected:
+ virtual void OnMarkDestroyed() {}
+
+ // -----------------------------------------------------------------------------
+ // Everything that isn't standard GL APIs
+ protected:
+ typedef gfx::SurfaceFormat SurfaceFormat;
+
+ public:
+ virtual void ReleaseSurface() {}
+
+ bool IsDestroyed() const {
+ // MarkDestroyed will mark all these as null.
+ return mContextLost && mSymbols.fUseProgram == nullptr;
+ }
+
+ GLContext* GetSharedContext() { return mSharedContext; }
+
+ /**
+ * Returns true if the thread on which this context was created is the
+ * currently executing thread.
+ */
+ bool IsValidOwningThread() const;
+
+ static void PlatformStartup();
+
+ public:
+ /**
+ * If this context wraps a double-buffered target, swap the back
+ * and front buffers. It should be assumed that after a swap, the
+ * contents of the new back buffer are undefined.
+ */
+ virtual bool SwapBuffers() { return false; }
+
+ /**
+ * Stores a damage region (in origin bottom left coordinates), which
+ * makes the next SwapBuffers call do eglSwapBuffersWithDamage if supported.
+ *
+ * Note that even if only part of the context is damaged, the entire buffer
+ * needs to be filled with up-to-date contents. This region is only a hint
+ * telling the system compositor which parts of the buffer were updated.
+ */
+ virtual void SetDamage(const nsIntRegion& aDamageRegion) {}
+
+ /**
+ * Get the buffer age. If it returns 0, that indicates the buffer state is
+ * unknown and the entire frame should be redrawn.
+ */
+ virtual GLint GetBufferAge() const { return 0; }
+
+ /**
+ * Defines a two-dimensional texture image for context target surface
+ */
+ virtual bool BindTexImage() { return false; }
+ /*
+ * Releases a color buffer that is being used as a texture
+ */
+ virtual bool ReleaseTexImage() { return false; }
+
+ virtual Maybe<SymbolLoader> GetSymbolLoader() const = 0;
+
+ void BindFB(GLuint fb) {
+ fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
+ MOZ_GL_ASSERT(this, !fb || fIsFramebuffer(fb));
+ }
+
+ void BindDrawFB(GLuint fb) {
+ fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb);
+ }
+
+ void BindReadFB(GLuint fb) {
+ fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, fb);
+ }
+
+ GLuint GetDrawFB() const {
+ return GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT);
+ }
+
+ GLuint GetReadFB() const {
+ auto bindEnum = LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT;
+ if (!IsSupported(GLFeature::split_framebuffer)) {
+ bindEnum = LOCAL_GL_FRAMEBUFFER_BINDING;
+ }
+ return GetIntAs<GLuint>(bindEnum);
+ }
+
+ GLuint GetFB() const {
+ const auto ret = GetDrawFB();
+ MOZ_ASSERT(ret == GetReadFB());
+ return ret;
+ }
+
+ private:
+ void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype,
+ GLint* range, GLint* precision) {
+ switch (precisiontype) {
+ case LOCAL_GL_LOW_FLOAT:
+ case LOCAL_GL_MEDIUM_FLOAT:
+ case LOCAL_GL_HIGH_FLOAT:
+ // Assume IEEE 754 precision
+ range[0] = 127;
+ range[1] = 127;
+ *precision = 23;
+ break;
+ case LOCAL_GL_LOW_INT:
+ case LOCAL_GL_MEDIUM_INT:
+ case LOCAL_GL_HIGH_INT:
+ // Some (most) hardware only supports single-precision floating-point
+ // numbers, which can accurately represent integers up to +/-16777216
+ range[0] = 24;
+ range[1] = 24;
+ *precision = 0;
+ break;
+ }
+ }
+
+ public:
+ virtual GLenum GetPreferredARGB32Format() const { return LOCAL_GL_RGBA; }
+
+ virtual GLenum GetPreferredEGLImageTextureTarget() const {
+#ifdef MOZ_WIDGET_GTK
+ return LOCAL_GL_TEXTURE_2D;
+#else
+ return IsExtensionSupported(OES_EGL_image_external)
+ ? LOCAL_GL_TEXTURE_EXTERNAL
+ : LOCAL_GL_TEXTURE_2D;
+#endif
+ }
+
+ virtual bool RenewSurface(widget::CompositorWidget* aWidget) { return false; }
+
+ // Shared code for GL extensions and GLX extensions.
+ static bool ListHasExtension(const GLubyte* extensions,
+ const char* extension);
+
+ public:
+ enum {
+ DebugFlagEnabled = 1 << 0,
+ DebugFlagTrace = 1 << 1,
+ DebugFlagAbortOnError = 1 << 2
+ };
+
+ const uint8_t mDebugFlags;
+ static uint8_t ChooseDebugFlags(CreateContextFlags createFlags);
+
+ protected:
+ RefPtr<GLContext> mSharedContext;
+
+ public:
+ // The thread id which this context was created.
+ Maybe<PlatformThreadId> mOwningThreadId;
+
+ protected:
+ GLContextSymbols mSymbols = {};
+
+ UniquePtr<GLBlitHelper> mBlitHelper;
+ UniquePtr<GLReadTexImageHelper> mReadTexImageHelper;
+
+ public:
+ GLBlitHelper* BlitHelper();
+ GLReadTexImageHelper* ReadTexImageHelper();
+
+ // Assumes shares are created by all sharing with the same global context.
+ bool SharesWith(const GLContext* other) const {
+ MOZ_ASSERT(!this->mSharedContext || !this->mSharedContext->mSharedContext);
+ MOZ_ASSERT(!other->mSharedContext ||
+ !other->mSharedContext->mSharedContext);
+ MOZ_ASSERT(!this->mSharedContext || !other->mSharedContext ||
+ this->mSharedContext == other->mSharedContext);
+
+ const GLContext* thisShared =
+ this->mSharedContext ? this->mSharedContext : this;
+ const GLContext* otherShared =
+ other->mSharedContext ? other->mSharedContext : other;
+
+ return thisShared == otherShared;
+ }
+
+ bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
+
+ // Does not check completeness.
+ void AttachBuffersToFB(GLuint colorTex, GLuint colorRB, GLuint depthRB,
+ GLuint stencilRB, GLuint fb,
+ GLenum target = LOCAL_GL_TEXTURE_2D);
+
+ // Passing null is fine if the value you'd get is 0.
+ bool AssembleOffscreenFBs(const GLuint colorMSRB, const GLuint depthRB,
+ const GLuint stencilRB, const GLuint texture,
+ GLuint* drawFB, GLuint* readFB);
+
+ protected:
+ SharedSurface* mLockedSurface = nullptr;
+
+ public:
+ void LockSurface(SharedSurface* surf) { mLockedSurface = surf; }
+
+ void UnlockSurface(SharedSurface* surf) {
+ MOZ_ASSERT(mLockedSurface == surf);
+ mLockedSurface = nullptr;
+ }
+
+ SharedSurface* GetLockedSurface() const { return mLockedSurface; }
+
+ bool IsOffscreen() const { return mDesc.isOffscreen; }
+
+ bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
+
+ bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const;
+
+ virtual bool Init();
+
+ private:
+ bool InitImpl();
+ void LoadMoreSymbols(const SymbolLoader& loader);
+ bool LoadExtSymbols(const SymbolLoader& loader, const SymLoadStruct* list,
+ GLExtensions ext);
+ bool LoadFeatureSymbols(const SymbolLoader& loader, const SymLoadStruct* list,
+ GLFeature feature);
+
+ protected:
+ void InitExtensions();
+
+ GLint mViewportRect[4] = {};
+ GLint mScissorRect[4] = {};
+
+ uint32_t mMaxTexOrRbSize = 0;
+ GLint mMaxTextureSize = 0;
+ GLint mMaxCubeMapTextureSize = 0;
+ GLint mMaxRenderbufferSize = 0;
+ GLint mMaxViewportDims[2] = {};
+ GLsizei mMaxSamples = 0;
+ bool mNeedsTextureSizeChecks = false;
+ bool mNeedsFlushBeforeDeleteFB = false;
+ bool mTextureAllocCrashesOnMapFailure = false;
+ const bool mWorkAroundDriverBugs;
+ mutable uint64_t mSyncGLCallCount = 0;
+
+ bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width,
+ GLsizei height) const {
+ if (mNeedsTextureSizeChecks) {
+ // some drivers incorrectly handle some large texture sizes that are below
+ // the max texture size that they report. So we check ourselves against
+ // our own values (mMax[CubeMap]TextureSize). see bug 737182 for Mac Intel
+ // 2D textures see bug 684882 for Mac Intel cube map textures see bug
+ // 814716 for Mesa Nouveau
+ GLsizei maxSize =
+ target == LOCAL_GL_TEXTURE_CUBE_MAP ||
+ (target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+ target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
+ ? mMaxCubeMapTextureSize
+ : mMaxTextureSize;
+ return width <= maxSize && height <= maxSize;
+ }
+ return true;
+ }
+
+ public:
+ auto MaxSamples() const { return uint32_t(mMaxSamples); }
+ auto MaxTextureSize() const { return uint32_t(mMaxTextureSize); }
+ auto MaxRenderbufferSize() const { return uint32_t(mMaxRenderbufferSize); }
+ auto MaxTexOrRbSize() const { return mMaxTexOrRbSize; }
+
+#ifdef MOZ_GL_DEBUG_BUILD
+ void CreatedProgram(GLContext* aOrigin, GLuint aName);
+ void CreatedShader(GLContext* aOrigin, GLuint aName);
+ void CreatedBuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
+ void CreatedQueries(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
+ void CreatedTextures(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
+ void CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
+ void CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
+ void DeletedProgram(GLContext* aOrigin, GLuint aName);
+ void DeletedShader(GLContext* aOrigin, GLuint aName);
+ void DeletedBuffers(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames);
+ void DeletedQueries(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames);
+ void DeletedTextures(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames);
+ void DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames);
+ void DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
+ const GLuint* aNames);
+
+ void SharedContextDestroyed(GLContext* aChild);
+ void ReportOutstandingNames();
+
+ struct NamedResource {
+ NamedResource() : origin(nullptr), name(0), originDeleted(false) {}
+
+ NamedResource(GLContext* aOrigin, GLuint aName)
+ : origin(aOrigin), name(aName), originDeleted(false) {}
+
+ GLContext* origin;
+ GLuint name;
+ bool originDeleted;
+
+ // for sorting
+ bool operator<(const NamedResource& aOther) const {
+ if (intptr_t(origin) < intptr_t(aOther.origin)) return true;
+ if (name < aOther.name) return true;
+ return false;
+ }
+ bool operator==(const NamedResource& aOther) const {
+ return origin == aOther.origin && name == aOther.name &&
+ originDeleted == aOther.originDeleted;
+ }
+ };
+
+ nsTArray<NamedResource> mTrackedPrograms;
+ nsTArray<NamedResource> mTrackedShaders;
+ nsTArray<NamedResource> mTrackedTextures;
+ nsTArray<NamedResource> mTrackedFramebuffers;
+ nsTArray<NamedResource> mTrackedRenderbuffers;
+ nsTArray<NamedResource> mTrackedBuffers;
+ nsTArray<NamedResource> mTrackedQueries;
+#endif
+
+ protected:
+ bool mHeavyGLCallsSinceLastFlush = false;
+
+ public:
+ void FlushIfHeavyGLCallsSinceLastFlush();
+ static bool ShouldSpew();
+ static bool ShouldDumpExts();
+
+ // --
+
+ void TexParams_SetClampNoMips(GLenum target = LOCAL_GL_TEXTURE_2D) {
+ fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
+ fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
+ fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
+ fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
+ }
+
+ // --
+
+ GLuint CreateFramebuffer() {
+ GLuint x = 0;
+ fGenFramebuffers(1, &x);
+ return x;
+ }
+ GLuint CreateRenderbuffer() {
+ GLuint x = 0;
+ fGenRenderbuffers(1, &x);
+ return x;
+ }
+ GLuint CreateTexture() {
+ GLuint x = 0;
+ fGenTextures(1, &x);
+ return x;
+ }
+
+ void DeleteFramebuffer(const GLuint x) { fDeleteFramebuffers(1, &x); }
+ void DeleteRenderbuffer(const GLuint x) { fDeleteRenderbuffers(1, &x); }
+ void DeleteTexture(const GLuint x) { fDeleteTextures(1, &x); }
+};
+
+bool DoesStringMatch(const char* aString, const char* aWantedString);
+
+void SplitByChar(const nsACString& str, const char delim,
+ std::vector<nsCString>* const out);
+
+template <size_t N>
+bool MarkBitfieldByString(const nsACString& str,
+ const char* const (&markStrList)[N],
+ std::bitset<N>* const out_markList) {
+ for (size_t i = 0; i < N; i++) {
+ if (str.Equals(markStrList[i])) {
+ (*out_markList)[i] = 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+template <size_t N>
+void MarkBitfieldByStrings(const std::vector<nsCString>& strList,
+ bool dumpStrings,
+ const char* const (&markStrList)[N],
+ std::bitset<N>* const out_markList) {
+ for (auto itr = strList.begin(); itr != strList.end(); ++itr) {
+ const nsACString& str = *itr;
+ const bool wasMarked = MarkBitfieldByString(str, markStrList, out_markList);
+ if (dumpStrings)
+ printf_stderr(" %s%s\n", str.BeginReading(), wasMarked ? "(*)" : "");
+ }
+}
+
+// -
+
+class Renderbuffer final {
+ public:
+ const WeakPtr<GLContext> weakGl;
+ const GLuint name;
+
+ private:
+ static GLuint Create(GLContext& gl) {
+ GLuint ret = 0;
+ gl.fGenRenderbuffers(1, &ret);
+ return ret;
+ }
+
+ public:
+ explicit Renderbuffer(GLContext& gl) : weakGl(&gl), name(Create(gl)) {}
+
+ ~Renderbuffer() {
+ const RefPtr<GLContext> gl = weakGl.get();
+ if (!gl || !gl->MakeCurrent()) return;
+ gl->fDeleteRenderbuffers(1, &name);
+ }
+};
+
+// -
+
+class Texture final {
+ public:
+ const WeakPtr<GLContext> weakGl;
+ const GLuint name;
+
+ private:
+ static GLuint Create(GLContext& gl) {
+ GLuint ret = 0;
+ gl.fGenTextures(1, &ret);
+ return ret;
+ }
+
+ public:
+ explicit Texture(GLContext& gl) : weakGl(&gl), name(Create(gl)) {}
+
+ ~Texture() {
+ const RefPtr<GLContext> gl = weakGl.get();
+ if (!gl || !gl->MakeCurrent()) return;
+ gl->fDeleteTextures(1, &name);
+ }
+};
+
+/**
+ * Helper function that creates a 2D texture aSize.width x aSize.height with
+ * storage type specified by aFormats. Returns GL texture object id.
+ *
+ * See mozilla::gl::CreateTexture.
+ */
+UniquePtr<Texture> CreateTexture(GLContext&, const gfx::IntSize& size);
+
+/**
+ * Helper function that calculates the number of bytes required per
+ * texel for a texture from its format and type.
+ */
+uint32_t GetBytesPerTexel(GLenum format, GLenum type);
+
+void MesaMemoryLeakWorkaround();
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* GLCONTEXT_H_ */
diff --git a/gfx/gl/GLContextCGL.h b/gfx/gl/GLContextCGL.h
new file mode 100644
index 0000000000..b065df4554
--- /dev/null
+++ b/gfx/gl/GLContextCGL.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTCGL_H_
+#define GLCONTEXTCGL_H_
+
+#include "GLContext.h"
+
+#include "OpenGL/OpenGL.h"
+
+#ifdef __OBJC__
+# include <AppKit/NSOpenGL.h>
+#else
+typedef void NSOpenGLContext;
+#endif
+
+#include <CoreGraphics/CGDisplayConfiguration.h>
+
+#include "mozilla/Atomics.h"
+
+class nsIWidget;
+
+namespace mozilla {
+namespace gl {
+
+class GLContextCGL : public GLContext {
+ friend class GLContextProviderCGL;
+
+ NSOpenGLContext* mContext;
+
+ mozilla::Atomic<bool> mActiveGPUSwitchMayHaveOccurred;
+
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override)
+ GLContextCGL(const GLContextDesc&, NSOpenGLContext* context);
+
+ ~GLContextCGL();
+
+ virtual GLContextType GetContextType() const override {
+ return GLContextType::CGL;
+ }
+
+ static GLContextCGL* Cast(GLContext* gl) {
+ MOZ_ASSERT(gl->GetContextType() == GLContextType::CGL);
+ return static_cast<GLContextCGL*>(gl);
+ }
+
+ NSOpenGLContext* GetNSOpenGLContext() const { return mContext; }
+ CGLContextObj GetCGLContext() const;
+
+ // Can be called on any thread
+ static void DisplayReconfigurationCallback(CGDirectDisplayID aDisplay,
+ CGDisplayChangeSummaryFlags aFlags,
+ void* aUserInfo);
+
+ // Call at the beginning of a frame, on contexts that should stay on the
+ // active GPU. This method will migrate the context to the new active GPU, if
+ // the active GPU has changed since the last call.
+ void MigrateToActiveGPU();
+
+ virtual bool MakeCurrentImpl() const override;
+
+ virtual bool IsCurrentImpl() const override;
+
+ virtual GLenum GetPreferredARGB32Format() const override;
+
+ virtual bool SwapBuffers() override;
+
+ virtual void GetWSIInfo(nsCString* const out) const override;
+
+ Maybe<SymbolLoader> GetSymbolLoader() const override;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLCONTEXTCGL_H_
diff --git a/gfx/gl/GLContextEAGL.h b/gfx/gl/GLContextEAGL.h
new file mode 100644
index 0000000000..6e137e7b70
--- /dev/null
+++ b/gfx/gl/GLContextEAGL.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTEAGL_H_
+#define GLCONTEXTEAGL_H_
+
+#include "GLContext.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <OpenGLES/EAGL.h>
+
+namespace mozilla {
+namespace gl {
+
+class GLContextEAGL : public GLContext {
+ friend class GLContextProviderEAGL;
+
+ EAGLContext* const mContext;
+
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEAGL, override)
+ GLContextEAGL(const GLContextDesc&, EAGLContext* context,
+ GLContext* sharedContext, ContextProfile profile);
+
+ ~GLContextEAGL();
+
+ virtual GLContextType GetContextType() const override {
+ return GLContextType::EAGL;
+ }
+
+ static GLContextEAGL* Cast(GLContext* gl) {
+ MOZ_ASSERT(gl->GetContextType() == GLContextType::EAGL);
+ return static_cast<GLContextEAGL*>(gl);
+ }
+
+ bool AttachToWindow(nsIWidget* aWidget);
+
+ EAGLContext* GetEAGLContext() const { return mContext; }
+
+ virtual bool MakeCurrentImpl() const override;
+
+ virtual bool IsCurrentImpl() const override;
+
+ Maybe<SymbolLoader> GetSymbolLoader() const override;
+
+ virtual bool IsDoubleBuffered() const override;
+
+ virtual bool SwapBuffers() override;
+
+ virtual void GetWSIInfo(nsCString* const out) const override;
+
+ virtual GLuint GetDefaultFramebuffer() override { return mBackbufferFB; }
+
+ virtual bool RenewSurface(widget::CompositorWidget*) override {
+ // FIXME: should use the passed widget instead of the existing one.
+ return RecreateRB();
+ }
+
+ private:
+ GLuint mBackbufferRB = 0;
+ GLuint mBackbufferFB = 0;
+
+ void* mLayer = nullptr;
+
+ bool RecreateRB();
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLCONTEXTEAGL_H_
diff --git a/gfx/gl/GLContextEGL.h b/gfx/gl/GLContextEGL.h
new file mode 100644
index 0000000000..5a88f4a2a2
--- /dev/null
+++ b/gfx/gl/GLContextEGL.h
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTEGL_H_
+#define GLCONTEXTEGL_H_
+
+#include "GLContext.h"
+#include "GLLibraryEGL.h"
+#include "nsRegion.h"
+#include <memory>
+
+namespace mozilla {
+namespace layers {
+class SurfaceTextureImage;
+} // namespace layers
+namespace widget {
+class CompositorWidget;
+} // namespace widget
+namespace gl {
+
+inline std::shared_ptr<EglDisplay> DefaultEglDisplay(
+ nsACString* const out_failureId) {
+ const auto lib = GLLibraryEGL::Get(out_failureId);
+ if (!lib) {
+ return nullptr;
+ }
+ return lib->DefaultDisplay(out_failureId);
+}
+
+// -
+
+class GLContextEGL final : public GLContext {
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override)
+
+ static RefPtr<GLContextEGL> CreateGLContext(
+ std::shared_ptr<EglDisplay>, const GLContextDesc&,
+ EGLConfig surfaceConfig, EGLSurface surface, const bool useGles,
+ EGLConfig contextConfig, nsACString* const out_failureId);
+
+ private:
+ GLContextEGL(std::shared_ptr<EglDisplay>, const GLContextDesc&,
+ EGLConfig surfaceConfig, EGLSurface surface, EGLContext context);
+ ~GLContextEGL();
+
+ public:
+ virtual GLContextType GetContextType() const override {
+ return GLContextType::EGL;
+ }
+
+ static GLContextEGL* Cast(GLContext* gl) {
+ MOZ_ASSERT(gl->GetContextType() == GLContextType::EGL);
+ return static_cast<GLContextEGL*>(gl);
+ }
+
+ bool Init() override;
+
+ virtual bool IsDoubleBuffered() const override { return mIsDoubleBuffered; }
+
+ void SetIsDoubleBuffered(bool aIsDB) { mIsDoubleBuffered = aIsDB; }
+
+ virtual bool IsANGLE() const override { return mEgl->mLib->IsANGLE(); }
+ virtual bool IsWARP() const override { return mEgl->mIsWARP; }
+
+ virtual bool BindTexImage() override;
+
+ virtual bool ReleaseTexImage() override;
+
+ void SetEGLSurfaceOverride(EGLSurface surf);
+ EGLSurface GetEGLSurfaceOverride() { return mSurfaceOverride; }
+
+ virtual bool MakeCurrentImpl() const override;
+
+ virtual bool IsCurrentImpl() const override;
+
+ virtual bool RenewSurface(widget::CompositorWidget* aWidget) override;
+
+ virtual void ReleaseSurface() override;
+
+ Maybe<SymbolLoader> GetSymbolLoader() const override;
+
+ virtual bool SwapBuffers() override;
+
+ virtual void SetDamage(const nsIntRegion& aDamageRegion) override;
+
+ GLint GetBufferAge() const override;
+
+ virtual void GetWSIInfo(nsCString* const out) const override;
+
+ EGLSurface GetEGLSurface() const { return mSurface; }
+
+ bool HasExtBufferAge() const;
+ bool HasKhrPartialUpdate() const;
+
+ bool BindTex2DOffscreen(GLContext* aOffscreen);
+ void UnbindTex2DOffscreen(GLContext* aOffscreen);
+ void BindOffscreenFramebuffer();
+
+ void Destroy();
+
+ static RefPtr<GLContextEGL> CreateWithoutSurface(
+ std::shared_ptr<EglDisplay>, const GLContextCreateDesc&,
+ nsACString* const out_FailureId);
+ static RefPtr<GLContextEGL> CreateEGLSurfacelessContext(
+ const std::shared_ptr<EglDisplay> display,
+ const GLContextCreateDesc& desc, nsACString* const out_failureId);
+
+ static EGLSurface CreateEGLSurfaceForCompositorWidget(
+ widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig);
+
+ static void DestroySurface(EglDisplay&, const EGLSurface aSurface);
+
+#ifdef MOZ_X11
+ static bool FindVisual(int* const out_visualId);
+#endif
+
+ protected:
+ friend class GLContextProviderEGL;
+ friend class GLContextEGLFactory;
+
+ virtual void OnMarkDestroyed() override;
+
+ public:
+ const std::shared_ptr<EglDisplay> mEgl;
+ const EGLConfig mSurfaceConfig;
+ const EGLContext mContext;
+
+ protected:
+ EGLSurface mSurface;
+ const EGLSurface mFallbackSurface;
+
+ EGLSurface mSurfaceOverride = EGL_NO_SURFACE;
+ bool mBound = false;
+
+ bool mIsPBuffer = false;
+ bool mIsDoubleBuffered = false;
+ bool mCanBindToTexture = false;
+ bool mShareWithEGLImage = false;
+ bool mOwnsContext = true;
+
+ nsIntRegion mDamageRegion;
+
+ static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(
+ EglDisplay&, EGLConfig, EGLenum bindToTextureFormat,
+ gfx::IntSize& pbsize);
+
+#ifdef MOZ_WAYLAND
+ static EGLSurface CreateWaylandOffscreenSurface(EglDisplay&, EGLConfig,
+ gfx::IntSize& pbsize);
+#endif
+
+ public:
+ EGLSurface CreateCompatibleSurface(void* aWindow) const;
+};
+
+bool CreateConfig(EglDisplay&, EGLConfig* aConfig, int32_t aDepth,
+ bool aEnableDepthBuffer, bool aUseGles,
+ bool aAllowFallback = true);
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLCONTEXTEGL_H_
diff --git a/gfx/gl/GLContextFeatures.cpp b/gfx/gl/GLContextFeatures.cpp
new file mode 100644
index 0000000000..b66e6b6bbf
--- /dev/null
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -0,0 +1,642 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContext.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace gl {
+
+const size_t kMAX_EXTENSION_GROUP_SIZE = 5;
+
+enum class GLVersion : uint32_t {
+ NONE = 0, // Feature is not supported natively by GL
+ GL1_2 = 120,
+ GL1_3 = 130,
+ GL2 = 200,
+ GL2_1 = 210,
+ GL3 = 300,
+ GL3_1 = 310,
+ GL3_2 = 320,
+ GL3_3 = 330,
+ GL4 = 400,
+ GL4_1 = 410,
+ GL4_2 = 420,
+ GL4_3 = 430,
+};
+
+enum class GLESVersion : uint32_t {
+ NONE = 0, // Feature is not support natively by GL ES
+ ES2 = 200,
+ ES3 = 300,
+ ES3_1 = 310,
+ ES3_2 = 320,
+};
+
+// ARB_ES2_compatibility is natively supported in OpenGL 4.1.
+static const GLVersion kGLCoreVersionForES2Compat = GLVersion::GL4_1;
+
+// ARB_ES3_compatibility is natively supported in OpenGL 4.3.
+static const GLVersion kGLCoreVersionForES3Compat = GLVersion::GL4_3;
+
+struct FeatureInfo {
+ const char* mName;
+
+ /* The (desktop) OpenGL version that provides this feature */
+ GLVersion mOpenGLVersion;
+
+ /* The OpenGL ES version that provides this feature */
+ GLESVersion mOpenGLESVersion;
+
+ /* If there is an ARB extension, and its function symbols are
+ * not decorated with an ARB suffix, then its extension ID should go
+ * here, and NOT in mExtensions. For example, ARB_vertex_array_object
+ * functions do not have an ARB suffix, because it is an extension that
+ * was created to match core GL functionality and will never differ.
+ * Some ARB extensions do have a suffix, if they were created before
+ * a core version of the functionality existed.
+ *
+ * If there is no such ARB extension, pass 0 (GLContext::Extension_None)
+ */
+ GLContext::GLExtensions mARBExtensionWithoutARBSuffix;
+
+ /* Extensions that also provide this feature */
+ GLContext::GLExtensions mExtensions[kMAX_EXTENSION_GROUP_SIZE];
+};
+
+static const FeatureInfo sFeatureInfoArr[] = {
+ {"bind_buffer_offset",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {
+
+ GLContext::EXT_transform_feedback, GLContext::NV_transform_feedback2,
+ GLContext::Extensions_End}},
+ {"blend_minmax",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_blend_minmax, GLContext::Extensions_End}},
+ {"clear_buffers",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}},
+ {"copy_buffer",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::ARB_copy_buffer,
+ {GLContext::Extensions_End}},
+ {"depth_texture",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_depth_texture, GLContext::OES_depth_texture,
+ // Intentionally avoid putting ANGLE_depth_texture here,
+ // it does not offer quite the same functionality.
+ GLContext::Extensions_End}},
+ {"draw_buffers",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_draw_buffers, GLContext::EXT_draw_buffers,
+ GLContext::Extensions_End}},
+ {"draw_buffers_indexed",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {GLContext::OES_draw_buffers_indexed, GLContext::Extensions_End}},
+ {"draw_instanced",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_draw_instanced, GLContext::EXT_draw_instanced,
+ GLContext::NV_draw_instanced, GLContext::ANGLE_instanced_arrays,
+ GLContext::Extensions_End}},
+ {"element_index_uint",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::OES_element_index_uint, GLContext::Extensions_End}},
+ {"ES2_compatibility",
+ kGLCoreVersionForES2Compat,
+ GLESVersion::ES2, // OpenGL ES version
+ GLContext::ARB_ES2_compatibility, // no suffix on ARB extension
+ {GLContext::Extensions_End}},
+ {"ES3_compatibility",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3, // OpenGL ES version
+ GLContext::ARB_ES3_compatibility, // no suffix on ARB extension
+ {GLContext::Extensions_End}},
+ {"EXT_color_buffer_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {GLContext::EXT_color_buffer_float, GLContext::Extensions_End}},
+ {// Removes clamping for float color outputs from frag shaders.
+ "frag_color_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_color_buffer_float, GLContext::EXT_color_buffer_float,
+ GLContext::EXT_color_buffer_half_float,
+ GLContext::CHROMIUM_color_buffer_float_rgba, GLContext::Extensions_End}},
+ {"frag_depth",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_frag_depth, GLContext::Extensions_End}},
+ {// Check for just the blit framebuffer blit part of
+ // ARB_framebuffer_object
+ "framebuffer_blit",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {GLContext::ANGLE_framebuffer_blit, GLContext::EXT_framebuffer_blit,
+ GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
+ {// Check for just the multisample renderbuffer part of
+ // ARB_framebuffer_object
+ "framebuffer_multisample",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {GLContext::ANGLE_framebuffer_multisample,
+ GLContext::APPLE_framebuffer_multisample,
+ GLContext::EXT_framebuffer_multisample,
+ GLContext::EXT_multisampled_render_to_texture,
+ GLContext::Extensions_End}},
+ {// ARB_framebuffer_object support
+ "framebuffer_object",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {GLContext::Extensions_End}},
+ {// EXT_framebuffer_object/OES_framebuffer_object support
+ "framebuffer_object_EXT_OES",
+ GLVersion::GL3,
+ GLESVersion::ES2,
+ GLContext::Extension_None,
+ {GLContext::EXT_framebuffer_object, GLContext::OES_framebuffer_object,
+ GLContext::Extensions_End}},
+ {"get_integer_indexed",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_draw_buffers2, GLContext::Extensions_End}},
+ {"get_integer64_indexed",
+ GLVersion::GL3_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}},
+ {"get_query_object_i64v",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_timer_query, GLContext::Extensions_End}},
+ {
+ "get_query_object_iv",
+ GLVersion::GL2,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}
+ /*
+ * XXX_get_query_object_iv only provide GetQueryObjectiv provided by
+ * ARB_occlusion_query (added by OpenGL 2.0).
+ */
+ },
+ {"gpu_shader4",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_gpu_shader4, GLContext::Extensions_End}},
+ {"instanced_arrays",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_instanced_arrays, GLContext::NV_instanced_arrays,
+ GLContext::ANGLE_instanced_arrays, GLContext::Extensions_End}},
+ {
+ "instanced_non_arrays",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_instanced_arrays, GLContext::Extensions_End}
+ /* This is an expanded version of `instanced_arrays` that allows for all
+ * enabled active attrib arrays to have non-zero divisors.
+ * ANGLE_instanced_arrays and NV_instanced_arrays forbid this, but GLES3
+ * has no such restriction.
+ */
+ },
+ {"internalformat_query",
+ GLVersion::GL4_2,
+ GLESVersion::ES3,
+ GLContext::ARB_internalformat_query,
+ {GLContext::Extensions_End}},
+ {"invalidate_framebuffer",
+ GLVersion::GL4_3,
+ GLESVersion::ES3,
+ GLContext::ARB_invalidate_subdata,
+ {GLContext::Extensions_End}},
+ {"map_buffer_range",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_map_buffer_range,
+ {GLContext::EXT_map_buffer_range, GLContext::Extensions_End}},
+ {"multiview",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ANGLE_multiview, GLContext::OVR_multiview2,
+ GLContext::Extensions_End}},
+ {
+ "occlusion_query",
+ GLVersion::GL2,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}
+ // XXX_occlusion_query depend on ARB_occlusion_query (added in
+ // OpenGL 2.0)
+ },
+ {
+ "occlusion_query_boolean",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3,
+ GLContext::ARB_ES3_compatibility,
+ {GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
+ /*
+ * XXX_occlusion_query_boolean provide ANY_SAMPLES_PASSED_CONSERVATIVE,
+ * but EXT_occlusion_query_boolean is only a OpenGL ES extension. But
+ * it is supported on desktop if ARB_ES3_compatibility because
+ * EXT_occlusion_query_boolean (added in OpenGL ES 3.0).
+ */
+ },
+ {
+ "occlusion_query2",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_occlusion_query2, GLContext::ARB_ES3_compatibility,
+ GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
+ /*
+ * XXX_occlusion_query2 (add in OpenGL 3.3) provide ANY_SAMPLES_PASSED,
+ * which is provided by ARB_occlusion_query2,
+ * EXT_occlusion_query_boolean (added in OpenGL ES 3.0) and
+ * ARB_ES3_compatibility
+ */
+ },
+ {"packed_depth_stencil",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_packed_depth_stencil, GLContext::OES_packed_depth_stencil,
+ GLContext::Extensions_End}},
+ {"prim_restart",
+ GLVersion::GL3_1,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {// GLContext::NV_primitive_restart, // Has different enum values.
+ GLContext::Extensions_End}},
+ {"prim_restart_fixed",
+ kGLCoreVersionForES3Compat,
+ GLESVersion::ES3,
+ GLContext::ARB_ES3_compatibility,
+ {GLContext::Extensions_End}},
+ {"provoking_vertex",
+ GLVersion::GL3_2,
+ GLESVersion::NONE,
+ GLContext::ARB_provoking_vertex,
+ {GLContext::ANGLE_provoking_vertex, GLContext::EXT_provoking_vertex,
+ GLContext::Extensions_End}},
+ {"query_counter",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
+ // EXT_timer_query does NOT support GL_TIMESTAMP retrieval with
+ // QueryCounter.
+ GLContext::Extensions_End}},
+ {
+ "query_objects",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_occlusion_query_boolean, GLContext::Extensions_End}
+ /*
+ * XXX_query_objects only provide entry points commonly supported by
+ * ARB_occlusion_query (added in OpenGL 2.0),
+ * EXT_occlusion_query_boolean (added in OpenGL ES 3.0), and
+ * ARB_timer_query (added in OpenGL 3.3)
+ */
+ },
+ {"query_time_elapsed",
+ GLVersion::GL3_3,
+ GLESVersion::NONE,
+ GLContext::ARB_timer_query,
+ {GLContext::ANGLE_timer_query, GLContext::EXT_disjoint_timer_query,
+ GLContext::EXT_timer_query, GLContext::Extensions_End}},
+ {"read_buffer",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}},
+ {"renderbuffer_color_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
+ GLContext::CHROMIUM_color_buffer_float_rgba, GLContext::Extensions_End}},
+ {"renderbuffer_color_half_float",
+ GLVersion::GL3,
+ GLESVersion::ES3_2,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_float, GLContext::EXT_color_buffer_float,
+ GLContext::EXT_color_buffer_half_float, GLContext::Extensions_End}},
+ {"robust_buffer_access_behavior",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ARB_robust_buffer_access_behavior,
+ GLContext::KHR_robust_buffer_access_behavior, GLContext::Extensions_End}},
+ {"robustness",
+ GLVersion::NONE,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ARB_robustness, GLContext::EXT_robustness,
+ GLContext::KHR_robustness, GLContext::Extensions_End}},
+ {"sRGB",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_sRGB,
+ {GLContext::EXT_sRGB, GLContext::EXT_framebuffer_sRGB,
+ GLContext::Extensions_End}},
+ {"sampler_objects",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::ARB_sampler_objects,
+ {GLContext::Extensions_End}},
+ {"seamless_cube_map_opt_in",
+ GLVersion::GL3_2,
+ GLESVersion::NONE,
+ GLContext::ARB_seamless_cube_map,
+ {GLContext::Extensions_End}},
+ {"shader_texture_lod",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_shader_texture_lod, GLContext::EXT_shader_texture_lod,
+ GLContext::Extensions_End}},
+ {// Do we have separate DRAW and READ framebuffer bind points?
+ "split_framebuffer",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_framebuffer_object,
+ {GLContext::ANGLE_framebuffer_blit,
+ GLContext::APPLE_framebuffer_multisample, GLContext::EXT_framebuffer_blit,
+ GLContext::NV_framebuffer_blit, GLContext::Extensions_End}},
+ {"standard_derivatives",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::OES_standard_derivatives, GLContext::Extensions_End}},
+ {"sync",
+ GLVersion::GL3_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_sync, GLContext::APPLE_sync, GLContext::Extensions_End}},
+ {"texture_3D",
+ GLVersion::GL1_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::OES_texture_3D, GLContext::Extensions_End}},
+ {"texture_3D_compressed",
+ GLVersion::GL1_3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_compression, GLContext::OES_texture_3D,
+ GLContext::Extensions_End}},
+ {"texture_3D_copy",
+ GLVersion::GL1_2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::EXT_copy_texture, GLContext::OES_texture_3D,
+ GLContext::Extensions_End}},
+ {"texture_compression_bptc",
+ GLVersion::GL4_2,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_compression_bptc,
+ GLContext::EXT_texture_compression_bptc, GLContext::Extensions_End}},
+ {"texture_compression_rgtc",
+ GLVersion::GL3,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_compression_rgtc,
+ GLContext::EXT_texture_compression_rgtc, GLContext::Extensions_End}},
+ {"texture_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_float, GLContext::OES_texture_float,
+ GLContext::Extensions_End}},
+ {"texture_float_linear",
+ GLVersion::GL3_1,
+ GLESVersion::NONE,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_float, GLContext::OES_texture_float_linear,
+ GLContext::Extensions_End}},
+ {
+ "texture_half_float",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
+ GLContext::NV_half_float, GLContext::Extensions_End}
+ /**
+ * We are not including OES_texture_half_float in this feature, because:
+ * GL_HALF_FLOAT = 0x140B
+ * GL_HALF_FLOAT_ARB = 0x140B == GL_HALF_FLOAT
+ * GL_HALF_FLOAT_NV = 0x140B == GL_HALF_FLOAT
+ * GL_HALF_FLOAT_OES = 0x8D61 != GL_HALF_FLOAT
+ * WebGL handles this specifically with an OES_texture_half_float check.
+ */
+ },
+ {"texture_half_float_linear",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_half_float_pixel, GLContext::ARB_texture_float,
+ GLContext::NV_half_float, GLContext::OES_texture_half_float_linear,
+ GLContext::Extensions_End}},
+ {"texture_non_power_of_two",
+ GLVersion::GL2,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::ARB_texture_non_power_of_two, GLContext::OES_texture_npot,
+ GLContext::Extensions_End}},
+ {"texture_norm16",
+ GLVersion::GL3_1,
+ GLESVersion::ES3_1,
+ GLContext::EXT_texture_norm16,
+ {GLContext::Extensions_End}},
+ {"texture_rg",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_rg,
+ {GLContext::Extensions_End}},
+ {"texture_storage",
+ GLVersion::GL4_2,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_storage,
+ {/*
+ * Not including GL_EXT_texture_storage here because it
+ * doesn't guarantee glTexStorage3D, which is required for
+ * WebGL 2.
+ */
+ GLContext::Extensions_End}},
+ {"texture_swizzle",
+ GLVersion::GL3_3,
+ GLESVersion::ES3,
+ GLContext::ARB_texture_swizzle,
+ {GLContext::Extensions_End}},
+ {"transform_feedback2",
+ GLVersion::GL4,
+ GLESVersion::ES3,
+ GLContext::ARB_transform_feedback2,
+ {GLContext::NV_transform_feedback2, GLContext::Extensions_End}},
+ {"uniform_buffer_object",
+ GLVersion::GL3_1,
+ GLESVersion::ES3,
+ GLContext::ARB_uniform_buffer_object,
+ {GLContext::Extensions_End}},
+ {"uniform_matrix_nonsquare",
+ GLVersion::GL2_1,
+ GLESVersion::ES3,
+ GLContext::Extension_None,
+ {GLContext::Extensions_End}},
+ {"vertex_array_object",
+ GLVersion::GL3,
+ GLESVersion::ES3,
+ GLContext::ARB_vertex_array_object, // ARB extension
+ {GLContext::OES_vertex_array_object, GLContext::APPLE_vertex_array_object,
+ GLContext::Extensions_End}}};
+
+static inline const FeatureInfo& GetFeatureInfo(GLFeature feature) {
+ static_assert(MOZ_ARRAY_LENGTH(sFeatureInfoArr) == size_t(GLFeature::EnumMax),
+ "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
+
+ MOZ_ASSERT(feature < GLFeature::EnumMax,
+ "GLContext::GetFeatureInfoInfo : unknown <feature>");
+
+ return sFeatureInfoArr[size_t(feature)];
+}
+
+static inline uint32_t ProfileVersionForFeature(GLFeature feature,
+ ContextProfile profile) {
+ MOZ_ASSERT(profile != ContextProfile::Unknown,
+ "GLContext::ProfileVersionForFeature : unknown <profile>");
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ if (profile == ContextProfile::OpenGLES)
+ return (uint32_t)featureInfo.mOpenGLESVersion;
+
+ return (uint32_t)featureInfo.mOpenGLVersion;
+}
+
+static bool IsFeaturePartOfProfileVersion(GLFeature feature,
+ ContextProfile profile,
+ unsigned int version) {
+ unsigned int profileVersion = ProfileVersionForFeature(feature, profile);
+
+ /**
+ * if `profileVersion` is zero, it means that no version of the profile
+ * added support for the feature.
+ */
+ return profileVersion && version >= profileVersion;
+}
+
+bool GLContext::IsFeatureProvidedByCoreSymbols(GLFeature feature) {
+ if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) return true;
+
+ if (IsExtensionSupported(
+ GetFeatureInfo(feature).mARBExtensionWithoutARBSuffix))
+ return true;
+
+ return false;
+}
+
+const char* GLContext::GetFeatureName(GLFeature feature) {
+ return GetFeatureInfo(feature).mName;
+}
+
+void GLContext::InitFeatures() {
+ for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
+ featureId++) {
+ GLFeature feature = GLFeature(featureId);
+
+ if (IsFeaturePartOfProfileVersion(feature, mProfile, mVersion)) {
+ mAvailableFeatures[featureId] = true;
+ continue;
+ }
+
+ mAvailableFeatures[featureId] = false;
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ if (IsExtensionSupported(featureInfo.mARBExtensionWithoutARBSuffix)) {
+ mAvailableFeatures[featureId] = true;
+ continue;
+ }
+
+ for (size_t j = 0; true; j++) {
+ MOZ_ASSERT(j < kMAX_EXTENSION_GROUP_SIZE,
+ "kMAX_EXTENSION_GROUP_SIZE too small");
+
+ if (featureInfo.mExtensions[j] == GLContext::Extensions_End) break;
+
+ if (IsExtensionSupported(featureInfo.mExtensions[j])) {
+ mAvailableFeatures[featureId] = true;
+ break;
+ }
+ }
+ }
+
+ if (ShouldDumpExts()) {
+ for (size_t featureId = 0; featureId < size_t(GLFeature::EnumMax);
+ featureId++) {
+ GLFeature feature = GLFeature(featureId);
+ printf_stderr("[%s] Feature::%s\n",
+ IsSupported(feature) ? "enabled" : "disabled",
+ GetFeatureName(feature));
+ }
+ }
+}
+
+void GLContext::MarkUnsupported(GLFeature feature) {
+ mAvailableFeatures[size_t(feature)] = false;
+
+ const FeatureInfo& featureInfo = GetFeatureInfo(feature);
+
+ for (size_t i = 0; true; i++) {
+ MOZ_ASSERT(i < kMAX_EXTENSION_GROUP_SIZE,
+ "kMAX_EXTENSION_GROUP_SIZE too small");
+
+ if (featureInfo.mExtensions[i] == GLContext::Extensions_End) break;
+
+ MarkExtensionUnsupported(featureInfo.mExtensions[i]);
+ }
+
+ MOZ_ASSERT(!IsSupported(feature), "GLContext::MarkUnsupported has failed!");
+
+ NS_WARNING(
+ nsPrintfCString("%s marked as unsupported", GetFeatureName(feature))
+ .get());
+}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContextGLX.h b/gfx/gl/GLContextGLX.h
new file mode 100644
index 0000000000..b6f6e9a959
--- /dev/null
+++ b/gfx/gl/GLContextGLX.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTGLX_H_
+#define GLCONTEXTGLX_H_
+
+#include "GLContext.h"
+#include "GLXLibrary.h"
+#include "mozilla/X11Util.h"
+
+namespace mozilla {
+namespace gl {
+
+class GLContextGLX : public GLContext {
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX, override)
+ static already_AddRefed<GLContextGLX> CreateGLContext(
+ const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> display,
+ GLXDrawable drawable, GLXFBConfig cfg, Drawable ownedPixmap = X11None);
+
+ static bool FindVisual(Display* display, int screen, int* const out_visualId);
+
+ // Finds a GLXFBConfig compatible with the provided window.
+ static bool FindFBConfigForWindow(
+ Display* display, int screen, Window window,
+ GLXFBConfig* const out_config, int* const out_visid, bool aWebRender);
+
+ virtual ~GLContextGLX();
+
+ GLContextType GetContextType() const override { return GLContextType::GLX; }
+
+ static GLContextGLX* Cast(GLContext* gl) {
+ MOZ_ASSERT(gl->GetContextType() == GLContextType::GLX);
+ return static_cast<GLContextGLX*>(gl);
+ }
+
+ bool Init() override;
+
+ bool MakeCurrentImpl() const override;
+
+ bool IsCurrentImpl() const override;
+
+ Maybe<SymbolLoader> GetSymbolLoader() const override;
+
+ bool IsDoubleBuffered() const override;
+
+ bool SwapBuffers() override;
+
+ GLint GetBufferAge() const override;
+
+ void GetWSIInfo(nsCString* const out) const override;
+
+ // Overrides the current GLXDrawable backing the context and makes the
+ // context current.
+ bool OverrideDrawable(GLXDrawable drawable);
+
+ // Undoes the effect of a drawable override.
+ bool RestoreDrawable();
+
+ private:
+ friend class GLContextProviderGLX;
+
+ GLContextGLX(const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> aDisplay,
+ GLXDrawable aDrawable, GLXContext aContext, bool aDoubleBuffered,
+ Drawable aOwnedPixmap = X11None);
+
+ const GLXContext mContext;
+ const std::shared_ptr<gfx::XlibDisplay> mDisplay;
+ const GLXDrawable mDrawable;
+ // The X pixmap associated with the GLX pixmap. If this is provided, then this
+ // class assumes responsibility for freeing both. Otherwise, the user of this
+ // class is responsibility for freeing the drawables.
+ const Drawable mOwnedPixmap;
+ const bool mDoubleBuffered;
+
+ GLXLibrary* const mGLX;
+
+ const bool mOwnsContext = true;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLCONTEXTGLX_H_
diff --git a/gfx/gl/GLContextProvider.h b/gfx/gl/GLContextProvider.h
new file mode 100644
index 0000000000..c63f1ada0b
--- /dev/null
+++ b/gfx/gl/GLContextProvider.h
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTPROVIDER_H_
+#define GLCONTEXTPROVIDER_H_
+
+#include "mozilla/AlreadyAddRefed.h"
+
+#include "GLContextTypes.h"
+#include "SurfaceTypes.h"
+
+#include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
+#include "nsStringFwd.h" // needed by GLContextProviderImpl.h below
+
+class nsIWidget;
+
+namespace mozilla {
+namespace widget {
+class CompositorWidget;
+}
+namespace gl {
+
+#define IN_GL_CONTEXT_PROVIDER_H
+
+// Null is always there
+#define GL_CONTEXT_PROVIDER_NAME GLContextProviderNull
+#include "GLContextProviderImpl.h"
+#undef GL_CONTEXT_PROVIDER_NAME
+
+#ifdef XP_WIN
+# define GL_CONTEXT_PROVIDER_NAME GLContextProviderWGL
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWGL
+# define DEFAULT_IMPL WGL
+#endif
+
+#ifdef XP_MACOSX
+# define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
+#endif
+
+#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
+#include "GLContextProviderImpl.h"
+#undef GL_CONTEXT_PROVIDER_NAME
+
+#if defined(MOZ_WIDGET_GTK)
+# ifdef MOZ_X11
+# define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# endif
+# define GL_CONTEXT_PROVIDER_NAME GLContextProviderLinux
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderLinux
+#endif
+
+#ifndef GL_CONTEXT_PROVIDER_DEFAULT
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
+#endif
+
+#if defined(MOZ_WIDGET_UIKIT)
+# define GL_CONTEXT_PROVIDER_NAME GLContextProviderEAGL
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# ifndef GL_CONTEXT_PROVIDER_DEFAULT
+# define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEAGL
+# endif
+#endif
+
+#ifdef MOZ_GL_PROVIDER
+# define GL_CONTEXT_PROVIDER_NAME MOZ_GL_PROVIDER
+# include "GLContextProviderImpl.h"
+# undef GL_CONTEXT_PROVIDER_NAME
+# define GL_CONTEXT_PROVIDER_DEFAULT MOZ_GL_PROVIDER
+#endif
+
+#ifdef GL_CONTEXT_PROVIDER_DEFAULT
+typedef GL_CONTEXT_PROVIDER_DEFAULT GLContextProvider;
+#else
+typedef GLContextProviderNull GLContextProvider;
+#endif
+
+#undef IN_GL_CONTEXT_PROVIDER_H
+
+} // namespace gl
+} // namespace mozilla
+
+#endif
diff --git a/gfx/gl/GLContextProviderCGL.mm b/gfx/gl/GLContextProviderCGL.mm
new file mode 100644
index 0000000000..2e205c1434
--- /dev/null
+++ b/gfx/gl/GLContextProviderCGL.mm
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContextProvider.h"
+#include "GLContextCGL.h"
+#include "GLLibraryLoader.h"
+#include "nsDebug.h"
+#include "nsIWidget.h"
+#include <OpenGL/gl.h>
+#include "gfxFailure.h"
+#include "mozilla/IntegerRange.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/StaticPrefs_gl.h"
+#include "mozilla/StaticPrefs_layout.h"
+#include "prenv.h"
+#include "prlink.h"
+#include "mozilla/ProfilerLabels.h"
+#include "MozFramebuffer.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/widget/CompositorWidget.h"
+#include "ScopedGLHelpers.h"
+
+#include <OpenGL/OpenGL.h>
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::widget;
+
+class CGLLibrary {
+ public:
+ bool EnsureInitialized() {
+ if (mInitialized) {
+ return true;
+ }
+ if (!mOGLLibrary) {
+ mOGLLibrary =
+ PR_LoadLibrary("/System/Library/Frameworks/OpenGL.framework/OpenGL");
+ if (!mOGLLibrary) {
+ NS_WARNING("Couldn't load OpenGL Framework.");
+ return false;
+ }
+ }
+
+ mInitialized = true;
+ return true;
+ }
+
+ const auto& Library() const { return mOGLLibrary; }
+
+ private:
+ bool mInitialized = false;
+ PRLibrary* mOGLLibrary = nullptr;
+};
+
+CGLLibrary sCGLLibrary;
+
+GLContextCGL::GLContextCGL(const GLContextDesc& desc, NSOpenGLContext* context)
+ : GLContext(desc), mContext(context) {
+ CGDisplayRegisterReconfigurationCallback(DisplayReconfigurationCallback,
+ this);
+}
+
+GLContextCGL::~GLContextCGL() {
+ MarkDestroyed();
+
+ CGDisplayRemoveReconfigurationCallback(DisplayReconfigurationCallback, this);
+
+ if (mContext) {
+ if ([NSOpenGLContext currentContext] == mContext) {
+ // Clear the current context before releasing. If we don't do
+ // this, the next time we call [NSOpenGLContext currentContext],
+ // "invalid context" will be printed to the console.
+ [NSOpenGLContext clearCurrentContext];
+ }
+ [mContext release];
+ }
+}
+
+CGLContextObj GLContextCGL::GetCGLContext() const {
+ return static_cast<CGLContextObj>([mContext CGLContextObj]);
+}
+
+bool GLContextCGL::MakeCurrentImpl() const {
+ if (mContext) {
+ GLContext::ResetTLSCurrentContext();
+
+ [mContext makeCurrentContext];
+ MOZ_ASSERT(IsCurrentImpl());
+ // Use non-blocking swap in "ASAP mode".
+ // ASAP mode means that rendering is iterated as fast as possible.
+ // ASAP mode is entered when layout.frame_rate=0 (requires restart).
+ // If swapInt is 1, then glSwapBuffers will block and wait for a vblank
+ // signal. When we're iterating as fast as possible, however, we want a
+ // non-blocking glSwapBuffers, which will happen when swapInt==0.
+ GLint swapInt = StaticPrefs::layout_frame_rate() == 0 ? 0 : 1;
+ [mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval];
+ }
+ return true;
+}
+
+bool GLContextCGL::IsCurrentImpl() const {
+ return [NSOpenGLContext currentContext] == mContext;
+}
+
+/* static */ void GLContextCGL::DisplayReconfigurationCallback(
+ CGDirectDisplayID aDisplay, CGDisplayChangeSummaryFlags aFlags,
+ void* aUserInfo) {
+ if (aFlags & kCGDisplaySetModeFlag) {
+ static_cast<GLContextCGL*>(aUserInfo)->mActiveGPUSwitchMayHaveOccurred =
+ true;
+ }
+}
+
+static NSOpenGLContext* CreateWithFormat(
+ const NSOpenGLPixelFormatAttribute* attribs) {
+ NSOpenGLPixelFormat* format =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ if (!format) {
+ NS_WARNING("Failed to create NSOpenGLPixelFormat.");
+ return nullptr;
+ }
+
+ NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format
+ shareContext:nullptr];
+
+ [format release];
+
+ return context;
+}
+
+// Get the "OpenGL display mask" for a fresh context. The return value of this
+// function depends on the time at which this function is called.
+// In practice, on a Macbook Pro with an integrated and a discrete GPU, this
+// function returns the display mask for the GPU that currently drives the
+// internal display.
+//
+// Quick reference of the concepts involved in the code below:
+// GPU switch: On Mac devices with an integrated and a discrete GPU, a GPU
+// switch changes which
+// GPU drives the internal display. Both GPUs are still usable at all times.
+// (When the integrated GPU is driving the internal display, using the
+// discrete GPU can incur a longer warm-up cost.)
+// Virtual screen: A CGL concept. A "virtual screen" corresponds to a GL
+// renderer. There's one
+// for the integrated GPU, one for each discrete GPU, and one for the Apple
+// software renderer. The list of virtual screens is
+// per-NSOpenGLPixelFormat; it is filtered down to only the renderers that
+// support the requirements from the pixel format attributes. Indexes into
+// this list (such as currentVirtualScreen) cannot be used interchangably
+// across different NSOpenGLPixelFormat instances.
+// Display mask: A bitset per GL renderer. Different renderers have disjoint
+// display masks. The
+// Apple software renderer has all bits zeroed. For each CGDirectDisplayID,
+// CGDisplayIDToOpenGLDisplayMask(displayID) returns a single bit in the
+// display mask.
+// CGDirectDisplayID: An ID for each (physical screen, GPU which can drive
+// this screen) pair. The
+// current CGDirectDisplayID for an NSScreen object can be obtained using
+// [[[screen deviceDescription] objectForKey:@"NSScreenNumber"]
+// unsignedIntValue]; it changes depending on which GPU is currently driving
+// the screen.
+static CGOpenGLDisplayMask GetFreshContextDisplayMask() {
+ NSOpenGLPixelFormatAttribute attribs[] = {NSOpenGLPFAAllowOfflineRenderers,
+ 0};
+ NSOpenGLPixelFormat* pixelFormat =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+ MOZ_RELEASE_ASSERT(pixelFormat);
+ NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat
+ shareContext:nullptr];
+ GLint displayMask = 0;
+ [pixelFormat getValues:&displayMask
+ forAttribute:NSOpenGLPFAScreenMask
+ forVirtualScreen:[context currentVirtualScreen]];
+ [pixelFormat release];
+ [context release];
+ return static_cast<CGOpenGLDisplayMask>(displayMask);
+}
+
+static bool IsSameGPU(CGOpenGLDisplayMask mask1, CGOpenGLDisplayMask mask2) {
+ if ((mask1 & mask2) != 0) {
+ return true;
+ }
+ // Both masks can be zero, when using the Apple software renderer.
+ return !mask1 && !mask2;
+}
+
+void GLContextCGL::MigrateToActiveGPU() {
+ if (!mActiveGPUSwitchMayHaveOccurred.compareExchange(true, false)) {
+ return;
+ }
+
+ CGOpenGLDisplayMask newPreferredDisplayMask = GetFreshContextDisplayMask();
+ NSOpenGLPixelFormat* pixelFormat = [mContext pixelFormat];
+ GLint currentVirtualScreen = [mContext currentVirtualScreen];
+ GLint currentDisplayMask = 0;
+ [pixelFormat getValues:&currentDisplayMask
+ forAttribute:NSOpenGLPFAScreenMask
+ forVirtualScreen:currentVirtualScreen];
+ if (IsSameGPU(currentDisplayMask, newPreferredDisplayMask)) {
+ // No "virtual screen" change needed.
+ return;
+ }
+
+ // Find the "virtual screen" with a display mask that matches
+ // newPreferredDisplayMask, if available, and switch the context over to it.
+ // This code was inspired by equivalent functionality in -[NSOpenGLContext
+ // update] which only kicks in for contexts that present via a CAOpenGLLayer.
+ for (const auto i : IntegerRange([pixelFormat numberOfVirtualScreens])) {
+ GLint displayMask = 0;
+ [pixelFormat getValues:&displayMask
+ forAttribute:NSOpenGLPFAScreenMask
+ forVirtualScreen:i];
+ if (IsSameGPU(displayMask, newPreferredDisplayMask)) {
+ CGLSetVirtualScreen([mContext CGLContextObj], i);
+ return;
+ }
+ }
+}
+
+GLenum GLContextCGL::GetPreferredARGB32Format() const { return LOCAL_GL_BGRA; }
+
+bool GLContextCGL::SwapBuffers() {
+ AUTO_PROFILER_LABEL("GLContextCGL::SwapBuffers", GRAPHICS);
+
+ // We do not have a default framebuffer. Just do a flush.
+ // Flushing is necessary if we want our IOSurfaces to have the correct
+ // content once they're picked up by the WindowServer from our CALayers.
+ fFlush();
+
+ return true;
+}
+
+void GLContextCGL::GetWSIInfo(nsCString* const out) const {
+ out->AppendLiteral("CGL");
+}
+
+Maybe<SymbolLoader> GLContextCGL::GetSymbolLoader() const {
+ const auto& lib = sCGLLibrary.Library();
+ return Some(SymbolLoader(*lib));
+}
+
+already_AddRefed<GLContext> GLContextProviderCGL::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ CreateContextFlags flags = CreateContextFlags::ALLOW_OFFLINE_RENDERER;
+ if (aForceAccelerated) {
+ flags |= CreateContextFlags::FORBID_SOFTWARE;
+ }
+ if (!aHardwareWebRender) {
+ flags |= CreateContextFlags::REQUIRE_COMPAT_PROFILE;
+ }
+ nsCString failureUnused;
+ return CreateHeadless({flags}, &failureUnused);
+}
+
+static RefPtr<GLContextCGL> CreateOffscreenFBOContext(
+ GLContextCreateDesc desc) {
+ if (!sCGLLibrary.EnsureInitialized()) {
+ return nullptr;
+ }
+
+ NSOpenGLContext* context = nullptr;
+
+ std::vector<NSOpenGLPixelFormatAttribute> attribs;
+ auto& flags = desc.flags;
+
+ if (!StaticPrefs::gl_allow_high_power()) {
+ flags &= ~CreateContextFlags::HIGH_POWER;
+ }
+ if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER ||
+ !(flags & CreateContextFlags::HIGH_POWER)) {
+ // This is really poorly named on Apple's part, but "AllowOfflineRenderers"
+ // means that we want to allow running on the iGPU instead of requiring the
+ // dGPU.
+ attribs.push_back(NSOpenGLPFAAllowOfflineRenderers);
+ }
+
+ if (flags & CreateContextFlags::FORBID_SOFTWARE) {
+ if (flags & CreateContextFlags::FORBID_HARDWARE) {
+ NS_WARNING("Both !hardware and !software.");
+ return nullptr;
+ }
+ attribs.push_back(NSOpenGLPFAAccelerated);
+ }
+ if (flags & CreateContextFlags::FORBID_HARDWARE) {
+ /* NSOpenGLPFARendererID:
+ * > OpenGL renderers that match the specified ID are preferred.
+ * > Constants to select specific renderers are provided in the
+ * > GLRenderers.h header of the OpenGL framework.
+ * > Of note is kCGLRendererGenericID which selects the Apple software
+ * > renderer.
+ * > The other constants select renderers for specific hardware vendors.
+ */
+ attribs.push_back(NSOpenGLPFARendererID);
+ attribs.push_back(kCGLRendererGenericID);
+ }
+
+ if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) {
+ auto coreAttribs = attribs;
+ coreAttribs.push_back(NSOpenGLPFAOpenGLProfile);
+ coreAttribs.push_back(NSOpenGLProfileVersion3_2Core);
+ coreAttribs.push_back(0);
+ context = CreateWithFormat(coreAttribs.data());
+ }
+
+ if (!context) {
+ attribs.push_back(0);
+ context = CreateWithFormat(attribs.data());
+ }
+
+ if (!context) {
+ NS_WARNING("Failed to create NSOpenGLContext.");
+ return nullptr;
+ }
+
+ RefPtr<GLContextCGL> glContext = new GLContextCGL({desc, true}, context);
+
+ if (flags & CreateContextFlags::PREFER_MULTITHREADED) {
+ CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine);
+ }
+ return glContext;
+}
+
+already_AddRefed<GLContext> GLContextProviderCGL::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ auto gl = CreateOffscreenFBOContext(desc);
+ if (!gl) {
+ *out_failureId = "FEATURE_FAILURE_CGL_FBO"_ns;
+ return nullptr;
+ }
+
+ if (!gl->Init()) {
+ *out_failureId = "FEATURE_FAILURE_CGL_INIT"_ns;
+ NS_WARNING("Failed during Init.");
+ return nullptr;
+ }
+
+ return gl.forget();
+}
+
+static RefPtr<GLContext> gGlobalContext;
+
+GLContext* GLContextProviderCGL::GetGlobalContext() {
+ static bool triedToCreateContext = false;
+ if (!triedToCreateContext) {
+ triedToCreateContext = true;
+
+ MOZ_RELEASE_ASSERT(!gGlobalContext);
+ nsCString discardFailureId;
+ RefPtr<GLContext> temp = CreateHeadless({}, &discardFailureId);
+ gGlobalContext = temp;
+
+ if (!gGlobalContext) {
+ NS_WARNING("Couldn't init gGlobalContext.");
+ }
+ }
+
+ return gGlobalContext;
+}
+
+void GLContextProviderCGL::Shutdown() { gGlobalContext = nullptr; }
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContextProviderEAGL.mm b/gfx/gl/GLContextProviderEAGL.mm
new file mode 100644
index 0000000000..6e27498028
--- /dev/null
+++ b/gfx/gl/GLContextProviderEAGL.mm
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContextProvider.h"
+#include "GLContextEAGL.h"
+#include "nsDebug.h"
+#include "nsIWidget.h"
+#include "gfxFailure.h"
+#include "prenv.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/ProfilerLabels.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/widget/CompositorWidget.h"
+
+#import <UIKit/UIKit.h>
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::widget;
+
+GLContextEAGL::GLContextEAGL(const GLContextDesc& desc, EAGLContext* context,
+ GLContext* sharedContext)
+ : GLContext(desc, sharedContext), mContext(context) {}
+
+GLContextEAGL::~GLContextEAGL() {
+ MakeCurrent();
+
+ if (mBackbufferFB) {
+ fDeleteFramebuffers(1, &mBackbufferFB);
+ }
+
+ if (mBackbufferRB) {
+ fDeleteRenderbuffers(1, &mBackbufferRB);
+ }
+
+ MarkDestroyed();
+
+ if (mLayer) {
+ mLayer = nil;
+ }
+
+ if (mContext) {
+ [EAGLContext setCurrentContext:nil];
+ [mContext release];
+ }
+}
+
+bool GLContextEAGL::AttachToWindow(nsIWidget* aWidget) {
+ // This should only be called once
+ MOZ_ASSERT(!mBackbufferFB && !mBackbufferRB);
+
+ UIView* view =
+ reinterpret_cast<UIView*>(aWidget->GetNativeData(NS_NATIVE_WIDGET));
+
+ if (!view) {
+ MOZ_CRASH("no view!");
+ }
+
+ mLayer = [view layer];
+
+ fGenFramebuffers(1, &mBackbufferFB);
+ return RecreateRB();
+}
+
+bool GLContextEAGL::RecreateRB() {
+ MakeCurrent();
+
+ CAEAGLLayer* layer = (CAEAGLLayer*)mLayer;
+
+ if (mBackbufferRB) {
+ // It doesn't seem to be enough to just call renderbufferStorage: below,
+ // we apparently have to recreate the RB.
+ fDeleteRenderbuffers(1, &mBackbufferRB);
+ mBackbufferRB = 0;
+ }
+
+ fGenRenderbuffers(1, &mBackbufferRB);
+ fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mBackbufferRB);
+
+ [mContext renderbufferStorage:LOCAL_GL_RENDERBUFFER fromDrawable:layer];
+
+ fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mBackbufferFB);
+ fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_RENDERBUFFER, mBackbufferRB);
+
+ return LOCAL_GL_FRAMEBUFFER_COMPLETE ==
+ fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+}
+
+bool GLContextEAGL::MakeCurrentImpl() const {
+ if (mContext) {
+ GLContext::ResetTLSCurrentContext();
+
+ if (![EAGLContext setCurrentContext:mContext]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GLContextEAGL::IsCurrentImpl() const {
+ return [EAGLContext currentContext] == mContext;
+}
+
+static PRFuncPtr GLAPIENTRY GetLoadedProcAddress(const char* const name) {
+ PRLibrary* lib = nullptr;
+ const auto& ret = PR_FindFunctionSymbolAndLibrary(name, &leakedLibRef);
+ if (lib) {
+ PR_UnloadLibrary(lib);
+ }
+ return ret;
+}
+
+Maybe<SymbolLoader> GLContextEAGL::GetSymbolLoader() const {
+ return Some(SymbolLoader(&GetLoadedProcAddress));
+}
+
+bool GLContextEAGL::IsDoubleBuffered() const { return true; }
+
+bool GLContextEAGL::SwapBuffers() {
+ AUTO_PROFILER_LABEL("GLContextEAGL::SwapBuffers", GRAPHICS);
+
+ [mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER];
+ return true;
+}
+
+void GLContextEAGL::GetWSIInfo(nsCString* const out) const {
+ out->AppendLiteral("EAGL");
+}
+
+static GLContextEAGL* GetGlobalContextEAGL() {
+ return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext());
+}
+
+static RefPtr<GLContext> CreateEAGLContext(const GLContextDesc& desc,
+ GLContextEAGL* sharedContext) {
+ EAGLRenderingAPI apis[] = {kEAGLRenderingAPIOpenGLES3,
+ kEAGLRenderingAPIOpenGLES2};
+
+ // Try to create a GLES3 context if we can, otherwise fall back to GLES2
+ EAGLContext* context = nullptr;
+ for (EAGLRenderingAPI api : apis) {
+ if (sharedContext) {
+ context = [[EAGLContext alloc]
+ initWithAPI:api
+ sharegroup:sharedContext->GetEAGLContext().sharegroup];
+ } else {
+ context = [[EAGLContext alloc] initWithAPI:api];
+ }
+
+ if (context) {
+ break;
+ }
+ }
+
+ if (!context) {
+ return nullptr;
+ }
+
+ RefPtr<GLContextEAGL> glContext =
+ new GLContextEAGL(desc, context, sharedContext);
+ if (!glContext->Init()) {
+ glContext = nullptr;
+ return nullptr;
+ }
+
+ return glContext;
+}
+
+already_AddRefed<GLContext> GLContextProviderEAGL::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ if (!aCompositorWidget) {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+
+ const GLContextDesc desc = {};
+ auto glContext = CreateEAGLContext(desc, GetGlobalContextEAGL());
+ if (!glContext) {
+ return nullptr;
+ }
+
+ if (!GLContextEAGL::Cast(glContext)->AttachToWindow(
+ aCompositorWidget->RealWidget())) {
+ return nullptr;
+ }
+
+ return glContext.forget();
+}
+
+already_AddRefed<GLContext> GLContextProviderEAGL::CreateHeadless(
+ const GLContextCreateDesc& createDesc, nsACString* const out_failureId) {
+ auto desc = GLContextDesc{createDesc};
+ desc.isOffcreen = true;
+ return CreateEAGLContext(desc, GetGlobalContextEAGL()).forget();
+}
+
+static RefPtr<GLContext> gGlobalContext;
+
+GLContext* GLContextProviderEAGL::GetGlobalContext() {
+ static bool triedToCreateContext = false;
+ if (!triedToCreateContext) {
+ triedToCreateContext = true;
+
+ MOZ_RELEASE_ASSERT(!gGlobalContext,
+ "GFX: Global GL context already initialized.");
+ RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE);
+ gGlobalContext = temp;
+
+ if (!gGlobalContext) {
+ MOZ_CRASH("Failed to create global context");
+ }
+ }
+
+ return gGlobalContext;
+}
+
+void GLContextProviderEAGL::Shutdown() { gGlobalContext = nullptr; }
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContextProviderEGL.cpp b/gfx/gl/GLContextProviderEGL.cpp
new file mode 100644
index 0000000000..cb47e285a5
--- /dev/null
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -0,0 +1,1261 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(MOZ_WIDGET_GTK)
+# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_EGL_WINDOW))
+# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \
+ (aWidget->AsGTK()->GetEGLNativeWindow())
+#elif defined(MOZ_WIDGET_ANDROID)
+# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->GetNativeData(NS_JAVA_SURFACE))
+# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \
+ (aWidget->AsAndroid()->GetEGLNativeWindow())
+#elif defined(XP_WIN)
+# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
+# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->AsWindows()->GetHwnd())
+#else
+# define GET_NATIVE_WINDOW_FROM_REAL_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
+# define GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget) \
+ ((EGLNativeWindowType)aWidget->RealWidget()->GetNativeData( \
+ NS_NATIVE_WINDOW))
+#endif
+
+#if defined(XP_UNIX)
+# ifdef MOZ_WIDGET_ANDROID
+# include <android/native_window.h>
+# include <android/native_window_jni.h>
+# include "mozilla/widget/AndroidCompositorWidget.h"
+# endif
+
+# define GLES2_LIB "libGLESv2.so"
+# define GLES2_LIB2 "libGLESv2.so.2"
+
+#elif defined(XP_WIN)
+# include "mozilla/widget/WinCompositorWidget.h"
+# include "nsIFile.h"
+
+# define GLES2_LIB "libGLESv2.dll"
+
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+
+# include <windows.h>
+#else
+# error "Platform not recognized"
+#endif
+
+#include "gfxCrashReporterUtils.h"
+#include "gfxFailure.h"
+#include "gfxPlatform.h"
+#include "gfxUtils.h"
+#include "GLBlitHelper.h"
+#include "GLContextEGL.h"
+#include "GLContextProvider.h"
+#include "GLLibraryEGL.h"
+#include "GLLibraryLoader.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/gfx/BuildConstants.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/widget/CompositorWidget.h"
+#include "nsDebug.h"
+#include "nsIWidget.h"
+#include "nsThreadUtils.h"
+#include "ScopedGLHelpers.h"
+
+#if defined(MOZ_WIDGET_GTK)
+# include "mozilla/widget/GtkCompositorWidget.h"
+# if defined(MOZ_WAYLAND)
+# include <gdk/gdkwayland.h>
+# include <wayland-egl.h>
+# include "mozilla/WidgetUtilsGtk.h"
+# include "mozilla/widget/nsWaylandDisplay.h"
+# endif
+#endif
+
+struct wl_egl_window;
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::widget;
+
+#if defined(MOZ_WAYLAND)
+class WaylandOffscreenGLSurface {
+ public:
+ WaylandOffscreenGLSurface(struct wl_surface* aWaylandSurface,
+ struct wl_egl_window* aEGLWindow);
+ ~WaylandOffscreenGLSurface();
+
+ private:
+ struct wl_surface* mWaylandSurface = nullptr;
+ struct wl_egl_window* mEGLWindow = nullptr;
+};
+
+static nsTHashMap<nsPtrHashKey<void>, WaylandOffscreenGLSurface*>
+ sWaylandOffscreenGLSurfaces;
+
+void DeleteWaylandOffscreenGLSurface(EGLSurface surface) {
+ auto entry = sWaylandOffscreenGLSurfaces.Lookup(surface);
+ if (entry) {
+ delete entry.Data();
+ entry.Remove();
+ }
+}
+#endif
+
+static bool CreateConfigScreen(EglDisplay&, EGLConfig* const aConfig,
+ const bool aEnableDepthBuffer,
+ const bool aUseGles);
+
+// append three zeros at the end of attribs list to work around
+// EGL implementation bugs that iterate until they find 0, instead of
+// EGL_NONE. See bug 948406.
+#define EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS \
+ LOCAL_EGL_NONE, 0, 0, 0
+
+static EGLint kTerminationAttribs[] = {
+ EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS};
+
+static int next_power_of_two(int v) {
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+
+ return v;
+}
+
+static bool is_power_of_two(int v) {
+ NS_ASSERTION(v >= 0, "bad value");
+
+ if (v == 0) return true;
+
+ return (v & (v - 1)) == 0;
+}
+
+static EGLSurface CreateFallbackSurface(EglDisplay& egl,
+ const EGLConfig& config) {
+ if (egl.IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
+ // We don't need a PBuffer surface in this case
+ return EGL_NO_SURFACE;
+ }
+
+ std::vector<EGLint> pbattrs;
+ pbattrs.push_back(LOCAL_EGL_WIDTH);
+ pbattrs.push_back(1);
+ pbattrs.push_back(LOCAL_EGL_HEIGHT);
+ pbattrs.push_back(1);
+
+ for (const auto& cur : kTerminationAttribs) {
+ pbattrs.push_back(cur);
+ }
+
+ EGLSurface surface = egl.fCreatePbufferSurface(config, pbattrs.data());
+ if (!surface) {
+ MOZ_CRASH("Failed to create fallback EGLSurface");
+ }
+
+ return surface;
+}
+
+static EGLSurface CreateSurfaceFromNativeWindow(
+ EglDisplay& egl, const EGLNativeWindowType window, const EGLConfig config) {
+ MOZ_ASSERT(window);
+ EGLSurface newSurface = EGL_NO_SURFACE;
+
+#ifdef MOZ_WIDGET_ANDROID
+ JNIEnv* const env = jni::GetEnvForThread();
+ ANativeWindow* const nativeWindow =
+ ANativeWindow_fromSurface(env, reinterpret_cast<jobject>(window));
+ if (!nativeWindow) {
+ gfxCriticalNote << "Failed to obtain native window from Surface";
+ return EGL_NO_SURFACE;
+ }
+ const auto& display = egl.mLib->fGetDisplay(EGL_DEFAULT_DISPLAY);
+ newSurface = egl.mLib->fCreateWindowSurface(display, config, nativeWindow, 0);
+ ANativeWindow_release(nativeWindow);
+#else
+ newSurface = egl.fCreateWindowSurface(config, window, 0);
+#endif
+ if (!newSurface) {
+ const auto err = egl.mLib->fGetError();
+ gfxCriticalNote << "Failed to create EGLSurface!: " << gfx::hexa(err);
+ }
+ return newSurface;
+}
+
+/* GLContextEGLFactory class was added as a friend of GLContextEGL
+ * so that it could access GLContextEGL::CreateGLContext. This was
+ * done so that a new function would not need to be added to the shared
+ * GLContextProvider interface.
+ */
+class GLContextEGLFactory {
+ public:
+ static already_AddRefed<GLContext> Create(EGLNativeWindowType aWindow,
+ bool aHardwareWebRender);
+ static already_AddRefed<GLContext> CreateImpl(EGLNativeWindowType aWindow,
+ bool aHardwareWebRender,
+ bool aUseGles);
+
+ private:
+ GLContextEGLFactory() = default;
+ ~GLContextEGLFactory() = default;
+};
+
+already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
+ EGLNativeWindowType aWindow, bool aHardwareWebRender, bool aUseGles) {
+ nsCString failureId;
+ const auto lib = GLLibraryEGL::Get(&failureId);
+ if (!lib) {
+ gfxCriticalNote << "Failed[3] to load EGL library: " << failureId.get();
+ return nullptr;
+ }
+ const auto egl = lib->CreateDisplay(true, &failureId);
+ if (!egl) {
+ gfxCriticalNote << "Failed[3] to create EGL library display: "
+ << failureId.get();
+ return nullptr;
+ }
+
+ bool doubleBuffered = true;
+
+ EGLConfig config;
+ if (aHardwareWebRender && egl->mLib->IsANGLE()) {
+ // Force enable alpha channel to make sure ANGLE use correct framebuffer
+ // formart
+ const int bpp = 32;
+ if (!CreateConfig(*egl, &config, bpp, false, aUseGles)) {
+ gfxCriticalNote << "Failed to create EGLConfig for WebRender ANGLE!";
+ return nullptr;
+ }
+ } else if (kIsLinux) {
+ const int bpp = 32;
+ if (!CreateConfig(*egl, &config, bpp, false, aUseGles)) {
+ gfxCriticalNote << "Failed to create EGLConfig for WebRender!";
+ return nullptr;
+ }
+ } else {
+ if (!CreateConfigScreen(*egl, &config,
+ /* aEnableDepthBuffer */ false, aUseGles)) {
+ gfxCriticalNote << "Failed to create EGLConfig!";
+ return nullptr;
+ }
+ }
+
+ EGLSurface surface = EGL_NO_SURFACE;
+ if (aWindow) {
+ surface = mozilla::gl::CreateSurfaceFromNativeWindow(*egl, aWindow, config);
+ if (!surface) {
+ return nullptr;
+ }
+ }
+
+ CreateContextFlags flags = CreateContextFlags::NONE;
+ if (aHardwareWebRender &&
+ StaticPrefs::gfx_webrender_prefer_robustness_AtStartup()) {
+ flags |= CreateContextFlags::PREFER_ROBUSTNESS;
+ }
+ if (aHardwareWebRender && aUseGles) {
+ flags |= CreateContextFlags::PREFER_ES3;
+ }
+ if (!aHardwareWebRender) {
+ flags |= CreateContextFlags::REQUIRE_COMPAT_PROFILE;
+ }
+
+ const auto desc = GLContextDesc{{flags}, false};
+ RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(
+ egl, desc, config, surface, aUseGles, config, &failureId);
+ if (!gl) {
+ const auto err = egl->mLib->fGetError();
+ gfxCriticalNote << "Failed to create EGLContext!: " << gfx::hexa(err);
+ GLContextEGL::DestroySurface(*egl, surface);
+ return nullptr;
+ }
+
+ gl->MakeCurrent();
+ gl->SetIsDoubleBuffered(doubleBuffered);
+
+#ifdef MOZ_WIDGET_GTK
+ if (surface) {
+ const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
+ egl->fSwapInterval(interval);
+ }
+#endif
+ if (aHardwareWebRender && egl->mLib->IsANGLE()) {
+ MOZ_ASSERT(doubleBuffered);
+ const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
+ egl->fSwapInterval(interval);
+ }
+ return gl.forget();
+}
+
+already_AddRefed<GLContext> GLContextEGLFactory::Create(
+ EGLNativeWindowType aWindow, bool aHardwareWebRender) {
+ bool preferGles;
+#if defined(MOZ_WIDGET_ANDROID)
+ preferGles = true;
+#else
+ preferGles = StaticPrefs::gfx_egl_prefer_gles_enabled_AtStartup();
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+ RefPtr<GLContext> glContext =
+ CreateImpl(aWindow, aHardwareWebRender, preferGles);
+#if !defined(MOZ_WIDGET_ANDROID)
+ if (!glContext) {
+ glContext = CreateImpl(aWindow, aHardwareWebRender, !preferGles);
+ }
+#endif // !defined(MOZ_WIDGET_ANDROID)
+ return glContext.forget();
+}
+
+/* static */
+EGLSurface GLContextEGL::CreateEGLSurfaceForCompositorWidget(
+ widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig) {
+ nsCString discardFailureId;
+ const auto egl = DefaultEglDisplay(&discardFailureId);
+ if (!egl) {
+ gfxCriticalNote << "Failed to load EGL library 6!";
+ return EGL_NO_SURFACE;
+ }
+
+ MOZ_ASSERT(aCompositorWidget);
+#ifdef MOZ_WAYLAND
+ // RenderCompositorEGL does not like EGL_NO_SURFACE as it fallbacks
+ // to SW rendering or claims itself as paused.
+ // In case we're missing valid native window because aCompositorWidget hidden,
+ // just create a fallback EGLSurface.
+ // Actual EGLSurface will be created by widget code later when
+ // aCompositorWidget becomes visible.
+ if (widget::GdkIsWaylandDisplay() && aCompositorWidget->IsHidden()) {
+ mozilla::gfx::IntSize pbSize(16, 16);
+ return CreateWaylandOffscreenSurface(*egl, aConfig, pbSize);
+ }
+#endif
+ EGLNativeWindowType window =
+ GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget);
+ if (!window) {
+ gfxCriticalNote << "window is null";
+ return EGL_NO_SURFACE;
+ }
+
+ return mozilla::gl::CreateSurfaceFromNativeWindow(*egl, window, aConfig);
+}
+
+GLContextEGL::GLContextEGL(const std::shared_ptr<EglDisplay> egl,
+ const GLContextDesc& desc, EGLConfig surfaceConfig,
+ EGLSurface surface, EGLContext context)
+ : GLContext(desc, nullptr, false),
+ mEgl(egl),
+ mSurfaceConfig(surfaceConfig),
+ mContext(context),
+ mSurface(surface),
+ mFallbackSurface(CreateFallbackSurface(*mEgl, mSurfaceConfig)) {
+#ifdef DEBUG
+ printf_stderr("Initializing context %p surface %p on display %p\n", mContext,
+ mSurface, mEgl->mDisplay);
+#endif
+}
+
+void GLContextEGL::OnMarkDestroyed() {
+ if (mSurfaceOverride != EGL_NO_SURFACE) {
+ SetEGLSurfaceOverride(EGL_NO_SURFACE);
+ }
+}
+
+GLContextEGL::~GLContextEGL() {
+ MarkDestroyed();
+
+ // Wrapped context should not destroy eglContext/Surface
+ if (!mOwnsContext) {
+ return;
+ }
+
+#ifdef DEBUG
+ printf_stderr("Destroying context %p surface %p on display %p\n", mContext,
+ mSurface, mEgl->mDisplay);
+#endif
+
+ mEgl->fDestroyContext(mContext);
+
+ DestroySurface(*mEgl, mSurface);
+ DestroySurface(*mEgl, mFallbackSurface);
+}
+
+bool GLContextEGL::Init() {
+ if (!GLContext::Init()) return false;
+
+ bool current = MakeCurrent();
+ if (!current) {
+ gfx::LogFailure("Couldn't get device attachments for device."_ns);
+ return false;
+ }
+
+ mShareWithEGLImage =
+ mEgl->HasKHRImageBase() &&
+ mEgl->IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
+ IsExtensionSupported(OES_EGL_image);
+
+ return true;
+}
+
+bool GLContextEGL::BindTexImage() {
+ if (!mSurface) return false;
+
+ if (mBound && !ReleaseTexImage()) return false;
+
+ EGLBoolean success =
+ mEgl->fBindTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
+ if (success == LOCAL_EGL_FALSE) return false;
+
+ mBound = true;
+ return true;
+}
+
+bool GLContextEGL::ReleaseTexImage() {
+ if (!mBound) return true;
+
+ if (!mSurface) return false;
+
+ EGLBoolean success;
+ success = mEgl->fReleaseTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
+ if (success == LOCAL_EGL_FALSE) return false;
+
+ mBound = false;
+ return true;
+}
+
+void GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
+ mSurfaceOverride = surf;
+ DebugOnly<bool> ok = MakeCurrent(true);
+ MOZ_ASSERT(ok);
+}
+
+bool GLContextEGL::MakeCurrentImpl() const {
+ EGLSurface surface =
+ (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride : mSurface;
+ if (!surface) {
+ surface = mFallbackSurface;
+ }
+
+ const bool succeeded = mEgl->fMakeCurrent(surface, surface, mContext);
+ if (!succeeded) {
+ const auto eglError = mEgl->mLib->fGetError();
+ if (eglError == LOCAL_EGL_CONTEXT_LOST) {
+ OnContextLostError();
+ } else {
+ NS_WARNING("Failed to make GL context current!");
+#ifdef DEBUG
+ printf_stderr("EGL Error: 0x%04x\n", eglError);
+#endif
+ }
+ }
+
+ return succeeded;
+}
+
+bool GLContextEGL::IsCurrentImpl() const {
+ return mEgl->mLib->fGetCurrentContext() == mContext;
+}
+
+bool GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
+ if (!mOwnsContext) {
+ return false;
+ }
+ // unconditionally release the surface and create a new one. Don't try to
+ // optimize this away. If we get here, then by definition we know that we want
+ // to get a new surface.
+ ReleaseSurface();
+ MOZ_ASSERT(aWidget);
+
+ EGLNativeWindowType nativeWindow =
+ GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget);
+#ifdef MOZ_WAYLAND
+ // In case we're missing native window on Wayland CompositorWidget is hidden.
+ // Don't create a fallback EGL surface but fails here.
+ // We need to repeat RenewSurface() when native window is available
+ // (CompositorWidget becomes visible).
+ if (GdkIsWaylandDisplay()) {
+ NS_WARNING("Failed to get native window");
+ return false;
+ }
+#endif
+ if (nativeWindow) {
+ mSurface = mozilla::gl::CreateSurfaceFromNativeWindow(*mEgl, nativeWindow,
+ mSurfaceConfig);
+ if (!mSurface) {
+ NS_WARNING("Failed to create EGLSurface from native window");
+ return false;
+ }
+ }
+ const bool ok = MakeCurrent(true);
+ MOZ_ASSERT(ok);
+#ifdef MOZ_WIDGET_GTK
+ if (mSurface) {
+ const int interval = gfxVars::SwapIntervalEGL() ? 1 : 0;
+ mEgl->fSwapInterval(interval);
+ }
+#endif
+ return ok;
+}
+
+void GLContextEGL::ReleaseSurface() {
+ if (mOwnsContext) {
+ DestroySurface(*mEgl, mSurface);
+ }
+ if (mSurface == mSurfaceOverride) {
+ mSurfaceOverride = EGL_NO_SURFACE;
+ }
+ mSurface = EGL_NO_SURFACE;
+}
+
+Maybe<SymbolLoader> GLContextEGL::GetSymbolLoader() const {
+ return mEgl->mLib->GetSymbolLoader();
+}
+
+bool GLContextEGL::SwapBuffers() {
+ EGLSurface surface =
+ mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;
+ if (surface) {
+ if ((mEgl->IsExtensionSupported(
+ EGLExtension::EXT_swap_buffers_with_damage) ||
+ mEgl->IsExtensionSupported(
+ EGLExtension::KHR_swap_buffers_with_damage))) {
+ std::vector<EGLint> rects;
+ for (auto iter = mDamageRegion.RectIter(); !iter.Done(); iter.Next()) {
+ const IntRect& r = iter.Get();
+ rects.push_back(r.X());
+ rects.push_back(r.Y());
+ rects.push_back(r.Width());
+ rects.push_back(r.Height());
+ }
+ mDamageRegion.SetEmpty();
+ return mEgl->fSwapBuffersWithDamage(surface, rects.data(),
+ rects.size() / 4);
+ }
+ return mEgl->fSwapBuffers(surface);
+ } else {
+ return false;
+ }
+}
+
+void GLContextEGL::SetDamage(const nsIntRegion& aDamageRegion) {
+ mDamageRegion = aDamageRegion;
+}
+
+void GLContextEGL::GetWSIInfo(nsCString* const out) const {
+ out->AppendLiteral("EGL_VENDOR: ");
+ out->Append(
+ (const char*)mEgl->mLib->fQueryString(mEgl->mDisplay, LOCAL_EGL_VENDOR));
+
+ out->AppendLiteral("\nEGL_VERSION: ");
+ out->Append(
+ (const char*)mEgl->mLib->fQueryString(mEgl->mDisplay, LOCAL_EGL_VERSION));
+
+ out->AppendLiteral("\nEGL_EXTENSIONS: ");
+ out->Append((const char*)mEgl->mLib->fQueryString(mEgl->mDisplay,
+ LOCAL_EGL_EXTENSIONS));
+
+#ifndef ANDROID // This query will crash some old android.
+ out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");
+ out->Append(
+ (const char*)mEgl->mLib->fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
+#endif
+}
+
+bool GLContextEGL::HasExtBufferAge() const {
+ return mEgl->IsExtensionSupported(EGLExtension::EXT_buffer_age);
+}
+
+bool GLContextEGL::HasKhrPartialUpdate() const {
+ return mEgl->IsExtensionSupported(EGLExtension::KHR_partial_update);
+}
+
+GLint GLContextEGL::GetBufferAge() const {
+ EGLSurface surface =
+ mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;
+
+ if (surface && (HasExtBufferAge() || HasKhrPartialUpdate())) {
+ EGLint result;
+ mEgl->fQuerySurface(surface, LOCAL_EGL_BUFFER_AGE_EXT, &result);
+ return result;
+ }
+
+ return 0;
+}
+
+#define LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ 0x6000
+
+RefPtr<GLContextEGL> GLContextEGL::CreateGLContext(
+ const std::shared_ptr<EglDisplay> egl, const GLContextDesc& desc,
+ EGLConfig surfaceConfig, EGLSurface surface, const bool useGles,
+ EGLConfig contextConfig, nsACString* const out_failureId) {
+ const auto& flags = desc.flags;
+
+ std::vector<EGLint> required_attribs;
+
+ if (useGles) {
+ // TODO: This fBindAPI could be more thread-safe
+ if (egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
+ *out_failureId = "FEATURE_FAILURE_EGL_ES"_ns;
+ NS_WARNING("Failed to bind API to GLES!");
+ return nullptr;
+ }
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);
+ if (flags & CreateContextFlags::PREFER_ES3) {
+ required_attribs.push_back(3);
+ } else {
+ required_attribs.push_back(2);
+ }
+ } else {
+ if (egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_API) == LOCAL_EGL_FALSE) {
+ *out_failureId = "FEATURE_FAILURE_EGL"_ns;
+ NS_WARNING("Failed to bind API to GL!");
+ return nullptr;
+ }
+ if (flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE) {
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK);
+ required_attribs.push_back(
+ LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);
+ required_attribs.push_back(2);
+ } else {
+ // !REQUIRE_COMPAT_PROFILE means core profle.
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK);
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_MAJOR_VERSION);
+ required_attribs.push_back(3);
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_MINOR_VERSION);
+ required_attribs.push_back(2);
+ }
+ }
+
+ if ((flags & CreateContextFlags::PREFER_EXACT_VERSION) &&
+ egl->mLib->IsANGLE()) {
+ required_attribs.push_back(
+ LOCAL_EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
+ required_attribs.push_back(LOCAL_EGL_FALSE);
+ }
+
+ const auto debugFlags = GLContext::ChooseDebugFlags(flags);
+ if (!debugFlags && flags & CreateContextFlags::NO_VALIDATION &&
+ egl->IsExtensionSupported(EGLExtension::KHR_create_context_no_error)) {
+ required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
+ required_attribs.push_back(LOCAL_EGL_TRUE);
+ }
+
+ if (flags & CreateContextFlags::PROVOKING_VERTEX_DONT_CARE &&
+ egl->IsExtensionSupported(
+ EGLExtension::MOZ_create_context_provoking_vertex_dont_care)) {
+ required_attribs.push_back(
+ LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ);
+ required_attribs.push_back(LOCAL_EGL_TRUE);
+ }
+
+ std::vector<EGLint> ext_robustness_attribs;
+ std::vector<EGLint> ext_rbab_attribs; // RBAB: Robust Buffer Access Behavior
+ std::vector<EGLint> khr_robustness_attribs;
+ std::vector<EGLint> khr_rbab_attribs; // RBAB: Robust Buffer Access Behavior
+ if (flags & CreateContextFlags::PREFER_ROBUSTNESS) {
+ std::vector<EGLint> base_robustness_attribs = required_attribs;
+ if (egl->IsExtensionSupported(
+ EGLExtension::NV_robustness_video_memory_purge)) {
+ base_robustness_attribs.push_back(
+ LOCAL_EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV);
+ base_robustness_attribs.push_back(LOCAL_EGL_TRUE);
+ }
+
+ if (egl->IsExtensionSupported(
+ EGLExtension::EXT_create_context_robustness)) {
+ ext_robustness_attribs = base_robustness_attribs;
+ ext_robustness_attribs.push_back(
+ LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
+ ext_robustness_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT);
+
+ if (gfxVars::AllowEglRbab()) {
+ ext_rbab_attribs = ext_robustness_attribs;
+ ext_rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
+ ext_rbab_attribs.push_back(LOCAL_EGL_TRUE);
+ }
+ }
+
+ if (egl->IsExtensionSupported(EGLExtension::KHR_create_context)) {
+ khr_robustness_attribs = base_robustness_attribs;
+ khr_robustness_attribs.push_back(
+ LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
+ khr_robustness_attribs.push_back(LOCAL_EGL_LOSE_CONTEXT_ON_RESET_KHR);
+
+ khr_rbab_attribs = khr_robustness_attribs;
+ khr_rbab_attribs.push_back(LOCAL_EGL_CONTEXT_FLAGS_KHR);
+ khr_rbab_attribs.push_back(
+ LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
+ }
+ }
+
+ const auto fnCreate = [&](const std::vector<EGLint>& attribs) {
+ auto terminated_attribs = attribs;
+
+ for (const auto& cur : kTerminationAttribs) {
+ terminated_attribs.push_back(cur);
+ }
+
+ return egl->fCreateContext(contextConfig, EGL_NO_CONTEXT,
+ terminated_attribs.data());
+ };
+
+ EGLContext context;
+ do {
+ if (!khr_rbab_attribs.empty()) {
+ context = fnCreate(khr_rbab_attribs);
+ if (context) break;
+ NS_WARNING("Failed to create EGLContext with khr_rbab_attribs");
+ }
+
+ if (!ext_rbab_attribs.empty()) {
+ context = fnCreate(ext_rbab_attribs);
+ if (context) break;
+ NS_WARNING("Failed to create EGLContext with ext_rbab_attribs");
+ }
+
+ if (!khr_robustness_attribs.empty()) {
+ context = fnCreate(khr_robustness_attribs);
+ if (context) break;
+ NS_WARNING("Failed to create EGLContext with khr_robustness_attribs");
+ }
+
+ if (!ext_robustness_attribs.empty()) {
+ context = fnCreate(ext_robustness_attribs);
+ if (context) break;
+ NS_WARNING("Failed to create EGLContext with ext_robustness_attribs");
+ }
+
+ context = fnCreate(required_attribs);
+ if (context) break;
+ NS_WARNING("Failed to create EGLContext with required_attribs");
+
+ *out_failureId = "FEATURE_FAILURE_EGL_CREATE"_ns;
+ return nullptr;
+ } while (false);
+ MOZ_ASSERT(context);
+
+ RefPtr<GLContextEGL> glContext =
+ new GLContextEGL(egl, desc, surfaceConfig, surface, context);
+ if (!glContext->Init()) {
+ *out_failureId = "FEATURE_FAILURE_EGL_INIT"_ns;
+ return nullptr;
+ }
+
+ if (GLContext::ShouldSpew()) {
+ printf_stderr("new GLContextEGL %p on EGLDisplay %p\n", glContext.get(),
+ egl->mDisplay);
+ }
+
+ return glContext;
+}
+
+// static
+EGLSurface GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(
+ EglDisplay& egl, EGLConfig config, EGLenum bindToTextureFormat,
+ mozilla::gfx::IntSize& pbsize) {
+ nsTArray<EGLint> pbattrs(16);
+ EGLSurface surface = nullptr;
+
+TRY_AGAIN_POWER_OF_TWO:
+ pbattrs.Clear();
+ pbattrs.AppendElement(LOCAL_EGL_WIDTH);
+ pbattrs.AppendElement(pbsize.width);
+ pbattrs.AppendElement(LOCAL_EGL_HEIGHT);
+ pbattrs.AppendElement(pbsize.height);
+
+ if (bindToTextureFormat != LOCAL_EGL_NONE) {
+ pbattrs.AppendElement(LOCAL_EGL_TEXTURE_TARGET);
+ pbattrs.AppendElement(LOCAL_EGL_TEXTURE_2D);
+
+ pbattrs.AppendElement(LOCAL_EGL_TEXTURE_FORMAT);
+ pbattrs.AppendElement(bindToTextureFormat);
+ }
+
+ for (const auto& cur : kTerminationAttribs) {
+ pbattrs.AppendElement(cur);
+ }
+
+ surface = egl.fCreatePbufferSurface(config, &pbattrs[0]);
+ if (!surface) {
+ if (!is_power_of_two(pbsize.width) || !is_power_of_two(pbsize.height)) {
+ if (!is_power_of_two(pbsize.width))
+ pbsize.width = next_power_of_two(pbsize.width);
+ if (!is_power_of_two(pbsize.height))
+ pbsize.height = next_power_of_two(pbsize.height);
+
+ NS_WARNING("Failed to create pbuffer, trying power of two dims");
+ goto TRY_AGAIN_POWER_OF_TWO;
+ }
+
+ NS_WARNING("Failed to create pbuffer surface");
+ return nullptr;
+ }
+
+ return surface;
+}
+
+#if defined(MOZ_WAYLAND)
+WaylandOffscreenGLSurface::WaylandOffscreenGLSurface(
+ struct wl_surface* aWaylandSurface, struct wl_egl_window* aEGLWindow)
+ : mWaylandSurface(aWaylandSurface), mEGLWindow(aEGLWindow) {}
+
+WaylandOffscreenGLSurface::~WaylandOffscreenGLSurface() {
+ if (mEGLWindow) {
+ wl_egl_window_destroy(mEGLWindow);
+ }
+ if (mWaylandSurface) {
+ wl_surface_destroy(mWaylandSurface);
+ }
+}
+
+// static
+EGLSurface GLContextEGL::CreateWaylandOffscreenSurface(
+ EglDisplay& egl, EGLConfig config, mozilla::gfx::IntSize& pbsize) {
+ wl_egl_window* eglwindow = nullptr;
+
+ struct wl_compositor* compositor =
+ gdk_wayland_display_get_wl_compositor(gdk_display_get_default());
+ struct wl_surface* wlsurface = wl_compositor_create_surface(compositor);
+ eglwindow = wl_egl_window_create(wlsurface, pbsize.width, pbsize.height);
+ if (!eglwindow) return nullptr;
+
+ const auto surface = egl.fCreateWindowSurface(
+ config, reinterpret_cast<EGLNativeWindowType>(eglwindow), 0);
+ if (surface) {
+ MOZ_DIAGNOSTIC_ASSERT(!sWaylandOffscreenGLSurfaces.Contains(surface));
+ sWaylandOffscreenGLSurfaces.LookupOrInsert(
+ surface, new WaylandOffscreenGLSurface(wlsurface, eglwindow));
+ }
+ return surface;
+}
+#endif
+
+static const EGLint kEGLConfigAttribsRGB16[] = {
+ LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
+ LOCAL_EGL_RED_SIZE, 5,
+ LOCAL_EGL_GREEN_SIZE, 6,
+ LOCAL_EGL_BLUE_SIZE, 5,
+ LOCAL_EGL_ALPHA_SIZE, 0};
+
+static const EGLint kEGLConfigAttribsRGB24[] = {
+ LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
+ LOCAL_EGL_RED_SIZE, 8,
+ LOCAL_EGL_GREEN_SIZE, 8,
+ LOCAL_EGL_BLUE_SIZE, 8,
+ LOCAL_EGL_ALPHA_SIZE, 0};
+
+static const EGLint kEGLConfigAttribsRGBA32[] = {
+ LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
+ LOCAL_EGL_RED_SIZE, 8,
+ LOCAL_EGL_GREEN_SIZE, 8,
+ LOCAL_EGL_BLUE_SIZE, 8,
+ LOCAL_EGL_ALPHA_SIZE, 8};
+
+bool CreateConfig(EglDisplay& aEgl, EGLConfig* aConfig, int32_t aDepth,
+ bool aEnableDepthBuffer, bool aUseGles, bool aAllowFallback) {
+ EGLConfig configs[64];
+ std::vector<EGLint> attribs;
+ EGLint ncfg = ArrayLength(configs);
+
+ switch (aDepth) {
+ case 16:
+ for (const auto& cur : kEGLConfigAttribsRGB16) {
+ attribs.push_back(cur);
+ }
+ break;
+ case 24:
+ for (const auto& cur : kEGLConfigAttribsRGB24) {
+ attribs.push_back(cur);
+ }
+ break;
+ case 32:
+ for (const auto& cur : kEGLConfigAttribsRGBA32) {
+ attribs.push_back(cur);
+ }
+ break;
+ default:
+ NS_ERROR("Unknown pixel depth");
+ return false;
+ }
+
+ if (aUseGles) {
+ attribs.push_back(LOCAL_EGL_RENDERABLE_TYPE);
+ attribs.push_back(LOCAL_EGL_OPENGL_ES2_BIT);
+ }
+ for (const auto& cur : kTerminationAttribs) {
+ attribs.push_back(cur);
+ }
+
+ if (!aEgl.fChooseConfig(attribs.data(), configs, ncfg, &ncfg) || ncfg < 1) {
+ return false;
+ }
+
+ Maybe<EGLConfig> fallbackConfig;
+
+ for (int j = 0; j < ncfg; ++j) {
+ EGLConfig config = configs[j];
+ EGLint r, g, b, a;
+ if (aEgl.fGetConfigAttrib(config, LOCAL_EGL_RED_SIZE, &r) &&
+ aEgl.fGetConfigAttrib(config, LOCAL_EGL_GREEN_SIZE, &g) &&
+ aEgl.fGetConfigAttrib(config, LOCAL_EGL_BLUE_SIZE, &b) &&
+ aEgl.fGetConfigAttrib(config, LOCAL_EGL_ALPHA_SIZE, &a) &&
+ ((aDepth == 16 && r == 5 && g == 6 && b == 5) ||
+ (aDepth == 24 && r == 8 && g == 8 && b == 8) ||
+ (aDepth == 32 && r == 8 && g == 8 && b == 8 && a == 8))) {
+ EGLint z;
+ if (aEnableDepthBuffer) {
+ if (!aEgl.fGetConfigAttrib(config, LOCAL_EGL_DEPTH_SIZE, &z) ||
+ z != 24) {
+ continue;
+ }
+ }
+#ifdef MOZ_X11
+ if (GdkIsX11Display()) {
+ int configVisualID;
+ if (!aEgl.fGetConfigAttrib(config, LOCAL_EGL_NATIVE_VISUAL_ID,
+ &configVisualID)) {
+ continue;
+ }
+
+ XVisualInfo visual_info_template, *visual_info;
+ int num_visuals;
+
+ visual_info_template.visualid = configVisualID;
+ visual_info =
+ XGetVisualInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
+ VisualIDMask, &visual_info_template, &num_visuals);
+
+ if (!visual_info || visual_info->depth != aDepth) {
+ if (aAllowFallback && !fallbackConfig) {
+ fallbackConfig = Some(config);
+ }
+ continue;
+ }
+ }
+#endif
+ *aConfig = config;
+ return true;
+ }
+ }
+
+ if (kIsLinux && fallbackConfig) {
+ *aConfig = fallbackConfig.value();
+ return true;
+ }
+
+ return false;
+}
+
+// Return true if a suitable EGLConfig was found and pass it out
+// through aConfig. Return false otherwise.
+//
+// NB: It's entirely legal for the returned EGLConfig to be valid yet
+// have the value null.
+static bool CreateConfigScreen(EglDisplay& egl, EGLConfig* const aConfig,
+ const bool aEnableDepthBuffer,
+ const bool aUseGles) {
+ int32_t depth = gfxVars::ScreenDepth();
+ if (CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles)) {
+ return true;
+ }
+#ifdef MOZ_WIDGET_ANDROID
+ // Bug 736005
+ // Android doesn't always support 16 bit so also try 24 bit
+ if (depth == 16) {
+ return CreateConfig(egl, aConfig, 24, aEnableDepthBuffer, aUseGles);
+ }
+ // Bug 970096
+ // Some devices that have 24 bit screens only support 16 bit OpenGL?
+ if (depth == 24) {
+ return CreateConfig(egl, aConfig, 16, aEnableDepthBuffer, aUseGles);
+ }
+#endif
+ return false;
+}
+
+already_AddRefed<GLContext> GLContextProviderEGL::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool /*aForceAccelerated*/) {
+ EGLNativeWindowType window = nullptr;
+ if (aCompositorWidget) {
+ window = GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget);
+ }
+ return GLContextEGLFactory::Create(window, aHardwareWebRender);
+}
+
+EGLSurface GLContextEGL::CreateCompatibleSurface(void* aWindow) const {
+ MOZ_ASSERT(aWindow);
+ MOZ_RELEASE_ASSERT(mSurfaceConfig != EGL_NO_CONFIG);
+
+ // NOTE: aWindow is an ANativeWindow
+ EGLSurface surface = mEgl->fCreateWindowSurface(
+ mSurfaceConfig, reinterpret_cast<EGLNativeWindowType>(aWindow), nullptr);
+ if (!surface) {
+ gfxCriticalError() << "CreateCompatibleSurface failed: "
+ << hexa(GetError());
+ }
+ return surface;
+}
+
+static void FillContextAttribs(bool es3, bool useGles, nsTArray<EGLint>* out) {
+ out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
+#ifdef MOZ_WAYLAND
+ if (GdkIsWaylandDisplay()) {
+ // Wayland on desktop does not support PBuffer or FBO.
+ // We create a dummy wl_egl_window instead.
+ out->AppendElement(LOCAL_EGL_WINDOW_BIT);
+ } else
+#endif
+ {
+ out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
+ }
+
+ if (useGles) {
+ out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
+ if (es3) {
+ out->AppendElement(LOCAL_EGL_OPENGL_ES3_BIT_KHR);
+ } else {
+ out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
+ }
+ }
+
+ out->AppendElement(LOCAL_EGL_RED_SIZE);
+ out->AppendElement(8);
+
+ out->AppendElement(LOCAL_EGL_GREEN_SIZE);
+ out->AppendElement(8);
+
+ out->AppendElement(LOCAL_EGL_BLUE_SIZE);
+ out->AppendElement(8);
+
+ out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
+ out->AppendElement(8);
+
+ out->AppendElement(LOCAL_EGL_DEPTH_SIZE);
+ out->AppendElement(0);
+
+ out->AppendElement(LOCAL_EGL_STENCIL_SIZE);
+ out->AppendElement(0);
+
+ // EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
+ out->AppendElement(LOCAL_EGL_NONE);
+ out->AppendElement(0);
+
+ out->AppendElement(0);
+ out->AppendElement(0);
+}
+
+/*
+/// Useful for debugging, but normally unused.
+static GLint GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib) {
+ EGLint bits = 0;
+ egl->fGetConfigAttrib(config, attrib, &bits);
+ MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
+
+ return bits;
+}
+*/
+
+static EGLConfig ChooseConfig(EglDisplay& egl, const GLContextCreateDesc& desc,
+ const bool useGles) {
+ nsTArray<EGLint> configAttribList;
+ FillContextAttribs(bool(desc.flags & CreateContextFlags::PREFER_ES3), useGles,
+ &configAttribList);
+
+ const EGLint* configAttribs = configAttribList.Elements();
+
+ // The sorting dictated by the spec for eglChooseConfig reasonably assures
+ // that a reasonable 'best' config is on top.
+ const EGLint kMaxConfigs = 1;
+ EGLConfig configs[kMaxConfigs];
+ EGLint foundConfigs = 0;
+ if (!egl.fChooseConfig(configAttribs, configs, kMaxConfigs, &foundConfigs) ||
+ foundConfigs == 0) {
+ return EGL_NO_CONFIG;
+ }
+
+ EGLConfig config = configs[0];
+ return config;
+}
+
+#ifdef MOZ_X11
+/* static */
+bool GLContextEGL::FindVisual(int* const out_visualId) {
+ nsCString discardFailureId;
+ const auto egl = DefaultEglDisplay(&discardFailureId);
+ if (!egl) {
+ gfxCriticalNote
+ << "GLContextEGL::FindVisual(): Failed to load EGL library!";
+ return false;
+ }
+
+ EGLConfig config;
+ const int bpp = 32;
+ if (!CreateConfig(*egl, &config, bpp, /* aEnableDepthBuffer */ false,
+ /* aUseGles */ false, /* aAllowFallback */ false)) {
+ // We are on a buggy driver. Do not return a visual so a fallback path can
+ // be used. See https://gitlab.freedesktop.org/mesa/mesa/-/issues/149
+ return false;
+ }
+ if (egl->fGetConfigAttrib(config, LOCAL_EGL_NATIVE_VISUAL_ID, out_visualId)) {
+ return true;
+ }
+ return false;
+}
+#endif
+
+/*static*/
+RefPtr<GLContextEGL> GLContextEGL::CreateWithoutSurface(
+ const std::shared_ptr<EglDisplay> egl, const GLContextCreateDesc& desc,
+ nsACString* const out_failureId) {
+ const auto WithUseGles = [&](const bool useGles) -> RefPtr<GLContextEGL> {
+#ifdef MOZ_WIDGET_GTK
+ // First try creating a context with no config and no surface, this is what
+ // we really want, and seems to be the only way to make selecting software
+ // Mesa init properly when it's not the first device.
+ if (egl->IsExtensionSupported(EGLExtension::KHR_no_config_context) &&
+ egl->IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
+ // These extensions have been supported by mesa and nvidia drivers
+ // since 2014 or earlier, this is the preferred code path
+ auto fullDesc = GLContextDesc{desc};
+ fullDesc.isOffscreen = true;
+ RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(
+ egl, fullDesc, EGL_NO_CONFIG, EGL_NO_SURFACE, useGles, EGL_NO_CONFIG,
+ out_failureId);
+ if (gl) {
+ return gl;
+ }
+ NS_WARNING(
+ "Failed to create GLContext with no config and no surface, will try "
+ "ChooseConfig");
+ }
+#endif
+
+ const EGLConfig surfaceConfig = ChooseConfig(*egl, desc, useGles);
+ if (surfaceConfig == EGL_NO_CONFIG) {
+ *out_failureId = "FEATURE_FAILURE_EGL_NO_CONFIG"_ns;
+ NS_WARNING("Failed to find a compatible config.");
+ return nullptr;
+ }
+
+ if (GLContext::ShouldSpew()) {
+ egl->DumpEGLConfig(surfaceConfig);
+ }
+ const EGLConfig contextConfig =
+ egl->IsExtensionSupported(EGLExtension::KHR_no_config_context)
+ ? nullptr
+ : surfaceConfig;
+
+ auto dummySize = mozilla::gfx::IntSize{16, 16};
+ EGLSurface surface = nullptr;
+#ifdef MOZ_WAYLAND
+ if (GdkIsWaylandDisplay()) {
+ surface = GLContextEGL::CreateWaylandOffscreenSurface(*egl, surfaceConfig,
+ dummySize);
+ } else
+#endif
+ {
+ surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(
+ *egl, surfaceConfig, LOCAL_EGL_NONE, dummySize);
+ }
+ if (!surface) {
+ *out_failureId = "FEATURE_FAILURE_EGL_POT"_ns;
+ NS_WARNING("Failed to create PBuffer for context!");
+ return nullptr;
+ }
+
+ auto fullDesc = GLContextDesc{desc};
+ fullDesc.isOffscreen = true;
+ RefPtr<GLContextEGL> gl =
+ GLContextEGL::CreateGLContext(egl, fullDesc, surfaceConfig, surface,
+ useGles, contextConfig, out_failureId);
+ if (!gl) {
+ NS_WARNING("Failed to create GLContext from PBuffer");
+ egl->fDestroySurface(surface);
+#if defined(MOZ_WAYLAND)
+ DeleteWaylandOffscreenGLSurface(surface);
+#endif
+ return nullptr;
+ }
+
+ return gl;
+ };
+
+ bool preferGles;
+#if defined(MOZ_WIDGET_ANDROID)
+ preferGles = true;
+#else
+ preferGles = StaticPrefs::gfx_egl_prefer_gles_enabled_AtStartup();
+#endif // defined(MOZ_WIDGET_ANDROID)
+ RefPtr<GLContextEGL> gl = WithUseGles(preferGles);
+#if !defined(MOZ_WIDGET_ANDROID)
+ if (!gl) {
+ gl = WithUseGles(!preferGles);
+ }
+#endif // !defined(MOZ_WIDGET_ANDROID)
+ return gl;
+}
+
+/*static*/
+void GLContextEGL::DestroySurface(EglDisplay& aEgl, const EGLSurface aSurface) {
+ if (aSurface != EGL_NO_SURFACE) {
+ if (!aEgl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
+ const EGLint err = aEgl.mLib->fGetError();
+ gfxCriticalNote << "Error in eglMakeCurrent: " << gfx::hexa(err);
+ }
+ if (!aEgl.fDestroySurface(aSurface)) {
+ const EGLint err = aEgl.mLib->fGetError();
+ gfxCriticalNote << "Error in eglDestroySurface: " << gfx::hexa(err);
+ }
+#if defined(MOZ_WAYLAND)
+ DeleteWaylandOffscreenGLSurface(aSurface);
+#endif
+ }
+}
+
+/*static*/
+already_AddRefed<GLContext> GLContextProviderEGL::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ const auto display = DefaultEglDisplay(out_failureId);
+ if (!display) {
+ return nullptr;
+ }
+ auto ret = GLContextEGL::CreateWithoutSurface(display, desc, out_failureId);
+ return ret.forget();
+}
+
+// Don't want a global context on Android as 1) share groups across 2 threads
+// fail on many Tegra drivers (bug 759225) and 2) some mobile devices have a
+// very strict limit on global number of GL contexts (bug 754257) and 3) each
+// EGL context eats 750k on B2G (bug 813783)
+/*static*/
+GLContext* GLContextProviderEGL::GetGlobalContext() { return nullptr; }
+
+// -
+
+/*static*/ void GLContextProviderEGL::Shutdown() { GLLibraryEGL::Shutdown(); }
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#undef EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
diff --git a/gfx/gl/GLContextProviderGLX.cpp b/gfx/gl/GLContextProviderGLX.cpp
new file mode 100644
index 0000000000..cdc5e7ce1a
--- /dev/null
+++ b/gfx/gl/GLContextProviderGLX.cpp
@@ -0,0 +1,908 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef MOZ_WIDGET_GTK
+# include <gdk/gdk.h>
+# include <gdk/gdkx.h>
+# define GET_NATIVE_WINDOW(aWidget) \
+ GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW))
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "X11UndefineNone.h"
+
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/Range.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Sprintf.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/StaticPrefs_layout.h"
+#include "mozilla/widget/CompositorWidget.h"
+#include "mozilla/widget/GtkCompositorWidget.h"
+#include "mozilla/Unused.h"
+
+#include "prenv.h"
+#include "GLContextProvider.h"
+#include "GLLibraryLoader.h"
+#include "nsDebug.h"
+#include "nsIWidget.h"
+#include "GLXLibrary.h"
+#include "gfxContext.h"
+#include "gfxEnv.h"
+#include "gfxPlatform.h"
+#include "GLContextGLX.h"
+#include "gfxUtils.h"
+#include "gfx2DGlue.h"
+#include "GLScreenBuffer.h"
+
+#include "gfxCrashReporterUtils.h"
+
+#ifdef MOZ_WIDGET_GTK
+# include "gfxPlatformGtk.h"
+#endif
+
+namespace mozilla::gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::widget;
+
+GLXLibrary sGLXLibrary;
+
+static inline bool HasExtension(const char* aExtensions,
+ const char* aRequiredExtension) {
+ return GLContext::ListHasExtension(
+ reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
+}
+
+bool GLXLibrary::EnsureInitialized(Display* aDisplay) {
+ if (mInitialized) {
+ return true;
+ }
+
+ // Don't repeatedly try to initialize.
+ if (mTriedInitializing) {
+ return false;
+ }
+ mTriedInitializing = true;
+
+ MOZ_ASSERT(aDisplay);
+ if (!aDisplay) {
+ return false;
+ }
+
+ // Force enabling s3 texture compression. (Bug 774134)
+ PR_SetEnv("force_s3tc_enable=true");
+
+ if (!mOGLLibrary) {
+ // see e.g. bug 608526: it is intrinsically interesting to know whether we
+ // have dynamically linked to libGL.so.1 because at least the NVIDIA
+ // implementation requires an executable stack, which causes mprotect calls,
+ // which trigger glibc bug
+ // http://sourceware.org/bugzilla/show_bug.cgi?id=12225
+ const char* libGLfilename = "libGL.so.1";
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+ libGLfilename = "libGL.so";
+#endif
+
+ const bool forceFeatureReport = false;
+ ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport);
+ mOGLLibrary = PR_LoadLibrary(libGLfilename);
+ if (!mOGLLibrary) {
+ NS_WARNING("Couldn't load OpenGL shared library.");
+ return false;
+ }
+ reporter.SetSuccessful();
+ }
+
+ if (gfxEnv::MOZ_GLX_DEBUG()) {
+ mDebug = true;
+ }
+
+#define SYMBOL(X) \
+ { \
+ (PRFuncPtr*)&mSymbols.f##X, { \
+ { "glX" #X } \
+ } \
+ }
+#define END_OF_SYMBOLS \
+ { \
+ nullptr, {} \
+ }
+
+ const SymLoadStruct symbols[] = {
+ /* functions that were in GLX 1.0 */
+ SYMBOL(DestroyContext),
+ SYMBOL(MakeCurrent),
+ SYMBOL(SwapBuffers),
+ SYMBOL(QueryVersion),
+ SYMBOL(GetConfig),
+ SYMBOL(GetCurrentContext),
+ SYMBOL(WaitGL),
+ SYMBOL(WaitX),
+
+ /* functions introduced in GLX 1.1 */
+ SYMBOL(QueryExtensionsString),
+ SYMBOL(GetClientString),
+ SYMBOL(QueryServerString),
+
+ /* functions introduced in GLX 1.3 */
+ SYMBOL(ChooseFBConfig),
+ SYMBOL(ChooseVisual),
+ SYMBOL(GetFBConfigAttrib),
+ SYMBOL(GetFBConfigs),
+ SYMBOL(CreatePixmap),
+ SYMBOL(DestroyPixmap),
+ SYMBOL(CreateNewContext),
+
+ // Core in GLX 1.4, ARB extension before.
+ {(PRFuncPtr*)&mSymbols.fGetProcAddress,
+ {{"glXGetProcAddress", "glXGetProcAddressARB"}}},
+ END_OF_SYMBOLS};
+
+ {
+ const SymbolLoader libLoader(*mOGLLibrary);
+ if (!libLoader.LoadSymbols(symbols)) {
+ NS_WARNING("Couldn't load required GLX symbols.");
+ return false;
+ }
+ }
+ const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
+
+ int screen = DefaultScreen(aDisplay);
+
+ {
+ int major, minor;
+ if (!fQueryVersion(aDisplay, &major, &minor) || major != 1 || minor < 3) {
+ NS_ERROR("GLX version older than 1.3. (released in 1998)");
+ return false;
+ }
+ }
+
+ const SymLoadStruct symbols_createcontext[] = {
+ SYMBOL(CreateContextAttribsARB), END_OF_SYMBOLS};
+
+ const SymLoadStruct symbols_videosync[] = {
+ SYMBOL(GetVideoSyncSGI), SYMBOL(WaitVideoSyncSGI), END_OF_SYMBOLS};
+
+ const SymLoadStruct symbols_swapcontrol[] = {SYMBOL(SwapIntervalEXT),
+ END_OF_SYMBOLS};
+
+ const SymLoadStruct symbols_querydrawable[] = {SYMBOL(QueryDrawable),
+ END_OF_SYMBOLS};
+
+ const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
+ if (pfnLoader.LoadSymbols(symbols)) return true;
+
+ ClearSymbols(symbols);
+ return false;
+ };
+
+ const char* clientVendor = fGetClientString(aDisplay, LOCAL_GLX_VENDOR);
+ const char* serverVendor =
+ fQueryServerString(aDisplay, screen, LOCAL_GLX_VENDOR);
+ const char* extensionsStr = fQueryExtensionsString(aDisplay, screen);
+
+ if (HasExtension(extensionsStr, "GLX_ARB_create_context") &&
+ HasExtension(extensionsStr, "GLX_ARB_create_context_profile") &&
+ fnLoadSymbols(symbols_createcontext)) {
+ mHasCreateContextAttribs = true;
+ }
+
+ if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness")) {
+ mHasRobustness = true;
+ }
+
+ if (HasExtension(extensionsStr, "GLX_NV_robustness_video_memory_purge")) {
+ mHasVideoMemoryPurge = true;
+ }
+
+ if (HasExtension(extensionsStr, "GLX_SGI_video_sync") &&
+ fnLoadSymbols(symbols_videosync)) {
+ mHasVideoSync = true;
+ }
+
+ if (!HasExtension(extensionsStr, "GLX_EXT_swap_control") ||
+ !fnLoadSymbols(symbols_swapcontrol)) {
+ NS_WARNING(
+ "GLX_swap_control unsupported, ASAP mode may still block on buffer "
+ "swaps.");
+ }
+
+ if (HasExtension(extensionsStr, "GLX_EXT_buffer_age") &&
+ fnLoadSymbols(symbols_querydrawable)) {
+ mHasBufferAge = true;
+ }
+
+ mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI");
+ mIsNVIDIA =
+ serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation");
+ mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa");
+
+ mInitialized = true;
+
+ // This needs to be after `fQueryServerString` is called so that the
+ // driver is loaded.
+ MesaMemoryLeakWorkaround();
+
+ return true;
+}
+
+bool GLXLibrary::SupportsVideoSync(Display* aDisplay) {
+ if (!EnsureInitialized(aDisplay)) {
+ return false;
+ }
+
+ return mHasVideoSync;
+}
+
+static int (*sOldErrorHandler)(Display*, XErrorEvent*);
+static XErrorEvent sErrorEvent = {};
+
+static int GLXErrorHandler(Display* display, XErrorEvent* ev) {
+ if (!sErrorEvent.error_code) {
+ sErrorEvent = *ev;
+ }
+ return 0;
+}
+
+GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
+ const char* const funcName,
+ Display* aDisplay)
+ : mGlx(glx), mFuncName(funcName), mDisplay(aDisplay) {
+ if (mGlx.mDebug) {
+ sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
+ }
+}
+
+GLXLibrary::WrapperScope::~WrapperScope() {
+ if (mGlx.mDebug) {
+ if (mDisplay) {
+ FinishX(mDisplay);
+ }
+ if (sErrorEvent.error_code) {
+ char buffer[100] = {};
+ if (mDisplay) {
+ XGetErrorText(mDisplay, sErrorEvent.error_code, buffer, sizeof(buffer));
+ } else {
+ SprintfLiteral(buffer, "%d", sErrorEvent.error_code);
+ }
+ printf_stderr("X ERROR after %s: %s (%i) - Request: %i.%i, Serial: %lu",
+ mFuncName, buffer, sErrorEvent.error_code,
+ sErrorEvent.request_code, sErrorEvent.minor_code,
+ sErrorEvent.serial);
+ MOZ_ASSERT_UNREACHABLE("AfterGLXCall sErrorEvent");
+ }
+ const auto was = XSetErrorHandler(sOldErrorHandler);
+ if (was != GLXErrorHandler) {
+ NS_WARNING("Concurrent XSetErrorHandlers");
+ }
+ }
+}
+
+// Returns the GTK display if available; otherwise, if a display was
+// previously opened by this method and is still open, returns a
+// reference to it; otherwise, opens a new connection. (The non-GTK
+// cases are similar to what we do for EGL.)
+std::shared_ptr<XlibDisplay> GLXLibrary::GetDisplay() {
+ std::shared_ptr<XlibDisplay> display;
+
+#ifdef MOZ_WIDGET_GTK
+ static const bool kHaveGtk = !!gdk_display_get_default();
+ if (kHaveGtk) {
+ display = XlibDisplay::Borrow(DefaultXDisplay());
+ }
+#endif
+ if (display) {
+ return display;
+ }
+
+ auto ownDisplay = mOwnDisplay.Lock();
+ display = ownDisplay->lock();
+ if (display) {
+ return display;
+ }
+
+ display = XlibDisplay::Open(nullptr);
+ if (NS_WARN_IF(!display)) {
+ return nullptr;
+ }
+ *ownDisplay = display;
+ return display;
+}
+
+already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
+ const GLContextDesc& desc, std::shared_ptr<XlibDisplay> display,
+ GLXDrawable drawable, GLXFBConfig cfg, Drawable ownedPixmap) {
+ GLXLibrary& glx = sGLXLibrary;
+
+ int isDoubleBuffered = 0;
+ int err = glx.fGetFBConfigAttrib(*display, cfg, LOCAL_GLX_DOUBLEBUFFER,
+ &isDoubleBuffered);
+ if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
+ if (ShouldSpew()) {
+ printf("[GLX] FBConfig is %sdouble-buffered\n",
+ isDoubleBuffered ? "" : "not ");
+ }
+ }
+
+ if (!glx.HasCreateContextAttribs()) {
+ NS_WARNING("Cannot create GLContextGLX without glxCreateContextAttribs");
+ return nullptr;
+ }
+
+ // -
+
+ const auto CreateWithAttribs =
+ [&](const std::vector<int>& attribs) -> RefPtr<GLContextGLX> {
+ auto terminated = attribs;
+ terminated.push_back(0);
+
+ const auto glxContext = glx.fCreateContextAttribs(
+ *display, cfg, nullptr, X11True, terminated.data());
+ if (!glxContext) return nullptr;
+ const RefPtr<GLContextGLX> ret = new GLContextGLX(
+ desc, display, drawable, glxContext, isDoubleBuffered, ownedPixmap);
+
+ if (!ret->Init()) return nullptr;
+
+ return ret;
+ };
+
+ // -
+
+ RefPtr<GLContextGLX> glContext;
+
+ std::vector<int> attribs;
+ attribs.insert(attribs.end(), {
+ LOCAL_GLX_RENDER_TYPE,
+ LOCAL_GLX_RGBA_TYPE,
+ });
+ if (glx.HasVideoMemoryPurge()) {
+ attribs.insert(attribs.end(),
+ {
+ LOCAL_GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV,
+ LOCAL_GL_TRUE,
+ });
+ }
+ const bool useCore =
+ !(desc.flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE);
+ if (useCore) {
+ attribs.insert(attribs.end(), {
+ LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB,
+ 3,
+ LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB,
+ 2,
+ LOCAL_GLX_CONTEXT_PROFILE_MASK_ARB,
+ LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
+ });
+ }
+
+ if (glx.HasRobustness()) {
+ auto withRobustness = attribs;
+ withRobustness.insert(withRobustness.end(),
+ {
+ LOCAL_GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ LOCAL_GLX_LOSE_CONTEXT_ON_RESET_ARB,
+ });
+
+ {
+ auto withRBAB = withRobustness;
+ withRBAB.insert(withRBAB.end(),
+ {
+ LOCAL_GLX_CONTEXT_FLAGS_ARB,
+ LOCAL_GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB,
+ });
+ if (!glContext) {
+ glContext = CreateWithAttribs(withRBAB);
+ if (!glContext) {
+ NS_WARNING("Failed to create+init GLContextGLX with RBAB");
+ }
+ }
+ }
+
+ if (!glContext) {
+ glContext = CreateWithAttribs(withRobustness);
+ if (!glContext) {
+ NS_WARNING("Failed to create+init GLContextGLX with Robustness");
+ }
+ }
+ }
+
+ if (!glContext) {
+ glContext = CreateWithAttribs(attribs);
+ if (!glContext) {
+ NS_WARNING("Failed to create+init GLContextGLX with required attribs");
+ }
+ }
+
+ return glContext.forget();
+}
+
+GLContextGLX::~GLContextGLX() {
+ MarkDestroyed();
+
+ // Wrapped context should not destroy glxContext/Surface
+ if (!mOwnsContext) {
+ return;
+ }
+
+ // see bug 659842 comment 76
+ bool success = mGLX->fMakeCurrent(*mDisplay, X11None, nullptr);
+ if (!success) {
+ NS_WARNING(
+ "glXMakeCurrent failed to release GL context before we call "
+ "glXDestroyContext!");
+ }
+
+ mGLX->fDestroyContext(*mDisplay, mContext);
+
+ // If we own the enclosed X pixmap, then free it after we free the enclosing
+ // GLX pixmap.
+ if (mOwnedPixmap) {
+ mGLX->fDestroyPixmap(*mDisplay, mDrawable);
+ XFreePixmap(*mDisplay, mOwnedPixmap);
+ }
+}
+
+bool GLContextGLX::Init() {
+ if (!GLContext::Init()) {
+ return false;
+ }
+
+ // EXT_framebuffer_object is not supported on Core contexts
+ // so we'll also check for ARB_framebuffer_object
+ if (!IsExtensionSupported(EXT_framebuffer_object) &&
+ !IsSupported(GLFeature::framebuffer_object))
+ return false;
+
+ return true;
+}
+
+bool GLContextGLX::MakeCurrentImpl() const {
+ if (mGLX->IsMesa()) {
+ // Read into the event queue to ensure that Mesa receives a
+ // DRI2InvalidateBuffers event before drawing. See bug 1280653.
+ Unused << XPending(*mDisplay);
+ }
+
+ const bool succeeded = mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
+ if (!succeeded) {
+ NS_WARNING("Failed to make GL context current!");
+ }
+
+ if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
+ // Many GLX implementations default to blocking until the next
+ // VBlank when calling glXSwapBuffers. We want to run unthrottled
+ // in ASAP mode. See bug 1280744.
+ const bool swapInterval = gfxVars::SwapIntervalGLX();
+ const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
+ const int interval = (swapInterval && !isASAP) ? 1 : 0;
+ mGLX->fSwapInterval(*mDisplay, mDrawable, interval);
+ }
+ return succeeded;
+}
+
+bool GLContextGLX::IsCurrentImpl() const {
+ return mGLX->fGetCurrentContext() == mContext;
+}
+
+Maybe<SymbolLoader> GLContextGLX::GetSymbolLoader() const {
+ const auto pfn = sGLXLibrary.GetGetProcAddress();
+ return Some(SymbolLoader(pfn));
+}
+
+bool GLContextGLX::IsDoubleBuffered() const { return mDoubleBuffered; }
+
+bool GLContextGLX::SwapBuffers() {
+ if (!mDoubleBuffered) return false;
+ mGLX->fSwapBuffers(*mDisplay, mDrawable);
+ return true;
+}
+
+GLint GLContextGLX::GetBufferAge() const {
+ if (!sGLXLibrary.SupportsBufferAge()) {
+ return 0;
+ }
+
+ GLuint result = 0;
+ mGLX->fQueryDrawable(*mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
+ &result);
+ if (result > INT32_MAX) {
+ // If the result can't fit, just assume the buffer cannot be reused.
+ return 0;
+ }
+ return result;
+}
+
+void GLContextGLX::GetWSIInfo(nsCString* const out) const {
+ int screen = DefaultScreen(mDisplay->get());
+
+ int majorVersion, minorVersion;
+ sGLXLibrary.fQueryVersion(*mDisplay, &majorVersion, &minorVersion);
+
+ out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
+
+ out->AppendLiteral("\nGLX_VENDOR(client): ");
+ out->Append(sGLXLibrary.fGetClientString(*mDisplay, LOCAL_GLX_VENDOR));
+
+ out->AppendLiteral("\nGLX_VENDOR(server): ");
+ out->Append(
+ sGLXLibrary.fQueryServerString(*mDisplay, screen, LOCAL_GLX_VENDOR));
+
+ out->AppendLiteral("\nExtensions: ");
+ out->Append(sGLXLibrary.fQueryExtensionsString(*mDisplay, screen));
+}
+
+bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) {
+ return mGLX->fMakeCurrent(*mDisplay, drawable, mContext);
+}
+
+bool GLContextGLX::RestoreDrawable() {
+ return mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
+}
+
+GLContextGLX::GLContextGLX(const GLContextDesc& desc,
+ std::shared_ptr<XlibDisplay> aDisplay,
+ GLXDrawable aDrawable, GLXContext aContext,
+ bool aDoubleBuffered, Drawable aOwnedPixmap)
+ : GLContext(desc, nullptr),
+ mContext(aContext),
+ mDisplay(aDisplay),
+ mDrawable(aDrawable),
+ mOwnedPixmap(aOwnedPixmap),
+ mDoubleBuffered(aDoubleBuffered),
+ mGLX(&sGLXLibrary) {}
+
+static bool AreCompatibleVisuals(Visual* one, Visual* two) {
+ if (one->c_class != two->c_class) {
+ return false;
+ }
+
+ if (one->red_mask != two->red_mask || one->green_mask != two->green_mask ||
+ one->blue_mask != two->blue_mask) {
+ return false;
+ }
+
+ if (one->bits_per_rgb != two->bits_per_rgb) {
+ return false;
+ }
+
+ return true;
+}
+
+already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
+ bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ if (!sGLXLibrary.EnsureInitialized(aXDisplay)) {
+ return nullptr;
+ }
+
+ // Currently, we take whatever Visual the window already has, and
+ // try to create an fbconfig for that visual. This isn't
+ // necessarily what we want in the long run; an fbconfig may not
+ // be available for the existing visual, or if it is, the GL
+ // performance might be suboptimal. But using the existing visual
+ // is a relatively safe intermediate step.
+
+ if (!aXDisplay) {
+ NS_ERROR("X Display required for GLX Context provider");
+ return nullptr;
+ }
+
+ if (!aXWindow) {
+ NS_ERROR("X window required for GLX Context provider");
+ return nullptr;
+ }
+
+ int xscreen = DefaultScreen(aXDisplay);
+
+ GLXFBConfig config;
+ int visid;
+ if (!GLContextGLX::FindFBConfigForWindow(aXDisplay, xscreen, aXWindow,
+ &config, &visid,
+ aHardwareWebRender)) {
+ return nullptr;
+ }
+
+ CreateContextFlags flags;
+ if (aHardwareWebRender) {
+ flags = CreateContextFlags::NONE; // WR needs GL3.2+
+ } else {
+ flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
+ }
+ return GLContextGLX::CreateGLContext(
+ {{flags}, false}, XlibDisplay::Borrow(aXDisplay), aXWindow, config);
+}
+
+already_AddRefed<GLContext> GLContextProviderGLX::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ if (!aCompositorWidget) {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+ GtkCompositorWidget* compWidget = aCompositorWidget->AsGTK();
+ MOZ_ASSERT(compWidget);
+
+ return CreateForWidget(DefaultXDisplay(), compWidget->XWindow(),
+ aHardwareWebRender, aForceAccelerated);
+}
+
+static bool ChooseConfig(GLXLibrary* glx, Display* display, int screen,
+ GLXFBConfig* const out_config, int* const out_visid) {
+ const int attribs[] = {
+ LOCAL_GLX_RENDER_TYPE,
+ LOCAL_GLX_RGBA_BIT,
+ LOCAL_GLX_DRAWABLE_TYPE,
+ LOCAL_GLX_PIXMAP_BIT,
+ LOCAL_GLX_X_RENDERABLE,
+ X11True,
+ LOCAL_GLX_RED_SIZE,
+ 8,
+ LOCAL_GLX_GREEN_SIZE,
+ 8,
+ LOCAL_GLX_BLUE_SIZE,
+ 8,
+ LOCAL_GLX_ALPHA_SIZE,
+ 8,
+ LOCAL_GLX_DEPTH_SIZE,
+ 0,
+ LOCAL_GLX_STENCIL_SIZE,
+ 0,
+ 0,
+ };
+
+ int numConfigs = 0;
+ const auto scopedConfigArr = glx->fChooseFBConfig(display, screen, attribs, &numConfigs);
+ const auto freeConfigList = MakeScopeExit([&]() {
+ if (scopedConfigArr) {
+ XFree(scopedConfigArr);
+ }
+ });
+ if (!scopedConfigArr || !numConfigs) return false;
+
+ // Issues with glxChooseFBConfig selection and sorting:
+ // * ALPHA_SIZE is sorted as 'largest total RGBA bits first'. If we don't
+ // request
+ // alpha bits, we'll probably get RGBA anyways, since 32 is more than 24.
+ // * DEPTH_SIZE is sorted largest first, including for `0` inputs.
+ // * STENCIL_SIZE is smallest first, but it might return `8` even though we
+ // ask for
+ // `0`.
+
+ // For now, we don't care about these. We *will* care when we do XPixmap
+ // sharing.
+
+ for (int i = 0; i < numConfigs; ++i) {
+ GLXFBConfig curConfig = scopedConfigArr[i];
+
+ int visid;
+ if (glx->fGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID,
+ &visid) != Success) {
+ continue;
+ }
+
+ if (!visid) continue;
+
+ *out_config = curConfig;
+ *out_visid = visid;
+ return true;
+ }
+
+ return false;
+}
+
+bool GLContextGLX::FindVisual(Display* display, int screen,
+ int* const out_visualId) {
+ if (!sGLXLibrary.EnsureInitialized(display)) {
+ return false;
+ }
+
+ XVisualInfo visualTemplate;
+ visualTemplate.screen = screen;
+
+ // Get all visuals of screen
+
+ int visualsLen = 0;
+ XVisualInfo* xVisuals =
+ XGetVisualInfo(display, VisualScreenMask, &visualTemplate, &visualsLen);
+ if (!xVisuals) {
+ return false;
+ }
+ const Range<XVisualInfo> visualInfos(xVisuals, visualsLen);
+ auto cleanupVisuals = MakeScopeExit([&] { XFree(xVisuals); });
+
+ // Get default visual info
+
+ Visual* defaultVisual = DefaultVisual(display, screen);
+ const auto defaultVisualInfo = [&]() -> const XVisualInfo* {
+ for (const auto& cur : visualInfos) {
+ if (cur.visual == defaultVisual) {
+ return &cur;
+ }
+ }
+ return nullptr;
+ }();
+ if (!defaultVisualInfo) {
+ MOZ_ASSERT(false);
+ return false;
+ }
+
+ const int bpp = 32;
+
+ for (auto& cur : visualInfos) {
+ const auto fnConfigMatches = [&](const int pname, const int expected) {
+ int actual;
+ if (sGLXLibrary.fGetConfig(display, &cur, pname, &actual)) {
+ return false;
+ }
+ return actual == expected;
+ };
+
+ // Check if visual is compatible.
+ if (cur.depth != bpp || cur.c_class != defaultVisualInfo->c_class) {
+ continue;
+ }
+
+ // Check if visual is compatible to GL requests.
+ if (fnConfigMatches(LOCAL_GLX_USE_GL, 1) &&
+ fnConfigMatches(LOCAL_GLX_DOUBLEBUFFER, 1) &&
+ fnConfigMatches(LOCAL_GLX_RED_SIZE, 8) &&
+ fnConfigMatches(LOCAL_GLX_GREEN_SIZE, 8) &&
+ fnConfigMatches(LOCAL_GLX_BLUE_SIZE, 8) &&
+ fnConfigMatches(LOCAL_GLX_ALPHA_SIZE, 8)) {
+ *out_visualId = cur.visualid;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GLContextGLX::FindFBConfigForWindow(
+ Display* display, int screen, Window window,
+ GLXFBConfig* const out_config, int* const out_visid, bool aWebRender) {
+ // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so
+ // we could probably do this first and replace the glXGetFBConfigs
+ // with glXChooseConfigs. Docs are sparklingly clear as always.
+ XWindowAttributes windowAttrs;
+ if (!XGetWindowAttributes(display, window, &windowAttrs)) {
+ NS_WARNING("[GLX] XGetWindowAttributes() failed");
+ return false;
+ }
+
+ GLXFBConfig* cfgs = nullptr;
+ const auto freeConfigList = MakeScopeExit([&]() {
+ if (cfgs) {
+ XFree(cfgs);
+ }
+ });
+ int numConfigs;
+ const int webrenderAttribs[] = {LOCAL_GLX_ALPHA_SIZE,
+ windowAttrs.depth == 32 ? 8 : 0,
+ LOCAL_GLX_DOUBLEBUFFER, X11True, 0};
+
+ if (aWebRender) {
+ cfgs = sGLXLibrary.fChooseFBConfig(display, screen, webrenderAttribs,
+ &numConfigs);
+ } else {
+ cfgs = sGLXLibrary.fGetFBConfigs(display, screen, &numConfigs);
+ }
+
+ if (!cfgs) {
+ NS_WARNING("[GLX] glXGetFBConfigs() failed");
+ return false;
+ }
+ NS_ASSERTION(numConfigs > 0, "No FBConfigs found!");
+
+ const VisualID windowVisualID = XVisualIDFromVisual(windowAttrs.visual);
+#ifdef DEBUG
+ printf("[GLX] window %lx has VisualID 0x%lx\n", window, windowVisualID);
+#endif
+
+ for (int i = 0; i < numConfigs; i++) {
+ int visid = X11None;
+ sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID,
+ &visid);
+ if (visid) {
+ // WebRender compatible GLX visual is configured
+ // at nsWindow::Create() by GLContextGLX::FindVisual(),
+ // just reuse it here.
+ if (windowVisualID == static_cast<VisualID>(visid)) {
+ *out_config = cfgs[i];
+ *out_visid = visid;
+ return true;
+ }
+ }
+ }
+
+ // We don't have a frame buffer visual which matches the GLX visual
+ // from GLContextGLX::FindVisual(). Let's try to find a near one and hope
+ // we're not on NVIDIA (Bug 1478454) as it causes X11 BadMatch error there.
+ for (int i = 0; i < numConfigs; i++) {
+ int visid = X11None;
+ sGLXLibrary.fGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID,
+ &visid);
+ if (visid) {
+ int depth;
+ Visual* visual;
+ FindVisualAndDepth(display, visid, &visual, &depth);
+ if (depth == windowAttrs.depth &&
+ AreCompatibleVisuals(windowAttrs.visual, visual)) {
+ *out_config = cfgs[i];
+ *out_visid = visid;
+ return true;
+ }
+ }
+ }
+
+ NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual");
+ return false;
+}
+
+static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
+ const GLContextCreateDesc& desc, const IntSize& size,
+ nsACString* const out_failureId) {
+ GLXLibrary* glx = &sGLXLibrary;
+ auto display = glx->GetDisplay();
+
+ if (!display || !glx->EnsureInitialized(*display)) return nullptr;
+
+ int screen = DefaultScreen(display->get());
+
+ GLXFBConfig config;
+ int visid;
+ if (!ChooseConfig(glx, *display, screen, &config, &visid)) {
+ NS_WARNING("Failed to find a compatible config.");
+ return nullptr;
+ }
+
+ Visual* visual;
+ int depth;
+ FindVisualAndDepth(*display, visid, &visual, &depth);
+
+ gfx::IntSize dummySize(16, 16);
+ const auto drawable =
+ XCreatePixmap(*display, DefaultRootWindow(display->get()),
+ dummySize.width, dummySize.height, depth);
+ if (!drawable) {
+ return nullptr;
+ }
+
+ // Handle slightly different signature between glXCreatePixmap and
+ // its pre-GLX-1.3 extension equivalent (though given the ABI, we
+ // might not need to).
+ const auto pixmap = glx->fCreatePixmap(*display, config, drawable, nullptr);
+ if (pixmap == 0) {
+ XFreePixmap(*display, drawable);
+ return nullptr;
+ }
+
+ auto fullDesc = GLContextDesc{desc};
+ fullDesc.isOffscreen = true;
+ return GLContextGLX::CreateGLContext(fullDesc, display, pixmap, config,
+ drawable);
+}
+
+/*static*/
+already_AddRefed<GLContext> GLContextProviderGLX::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ IntSize dummySize = IntSize(16, 16);
+ return CreateOffscreenPixmapContext(desc, dummySize, out_failureId);
+}
+
+/*static*/
+GLContext* GLContextProviderGLX::GetGlobalContext() {
+ // Context sharing not supported.
+ return nullptr;
+}
+
+/*static*/
+void GLContextProviderGLX::Shutdown() {}
+
+} // namespace mozilla::gl
diff --git a/gfx/gl/GLContextProviderImpl.h b/gfx/gl/GLContextProviderImpl.h
new file mode 100644
index 0000000000..e7aaeeaa62
--- /dev/null
+++ b/gfx/gl/GLContextProviderImpl.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef IN_GL_CONTEXT_PROVIDER_H
+# error GLContextProviderImpl.h must only be included from GLContextProvider.h
+#endif
+
+#ifndef GL_CONTEXT_PROVIDER_NAME
+# error GL_CONTEXT_PROVIDER_NAME not defined
+#endif
+#if defined(MOZ_WIDGET_ANDROID)
+# include "GLTypes.h" // for EGLSurface and EGLConfig
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+class GL_CONTEXT_PROVIDER_NAME {
+ public:
+ /**
+ * Create a context that renders to the surface of the widget represented by
+ * the compositor widget that is passed in. The context is always created
+ * with an RGB pixel format, with no alpha, depth or stencil.
+ * If any of those features are needed, either use a framebuffer, or
+ * use CreateOffscreen.
+ *
+ * This context will attempt to share resources with all other window
+ * contexts. As such, it's critical that resources allocated that are not
+ * needed by other contexts be deleted before the context is destroyed.
+ *
+ * The GetSharedContext() method will return non-null if sharing
+ * was successful.
+ *
+ * Note: a context created for a widget /must not/ hold a strong
+ * reference to the widget; otherwise a cycle can be created through
+ * a GL layer manager.
+ *
+ * @param aCompositorWidget Widget whose surface to create a context for
+ * @param aForceAccelerated true if only accelerated contexts are allowed
+ *
+ * @return Context to use for the window
+ */
+ static already_AddRefed<GLContext> CreateForCompositorWidget(
+ mozilla::widget::CompositorWidget* aCompositorWidget,
+ bool aHardwareWebRender, bool aForceAccelerated);
+
+ /// Just create a context. We'll add offscreen stuff ourselves.
+ static already_AddRefed<GLContext> CreateHeadless(
+ const GLContextCreateDesc&, nsACString* const out_failureId);
+
+ /**
+ * Get a pointer to the global context, creating it if it doesn't exist.
+ */
+ static GLContext* GetGlobalContext();
+
+ /**
+ * Free any resources held by this Context Provider.
+ */
+ static void Shutdown();
+};
diff --git a/gfx/gl/GLContextProviderLinux.cpp b/gfx/gl/GLContextProviderLinux.cpp
new file mode 100644
index 0000000000..7205449387
--- /dev/null
+++ b/gfx/gl/GLContextProviderLinux.cpp
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "prenv.h"
+
+#include "GLContextProvider.h"
+#include "mozilla/gfx/gfxVars.h"
+
+namespace mozilla::gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::widget;
+
+#ifdef MOZ_X11
+static class GLContextProviderGLX sGLContextProviderGLX;
+#endif
+static class GLContextProviderEGL sGLContextProviderEGL;
+
+already_AddRefed<GLContext> GLContextProviderLinux::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ if (gfxVars::UseEGL()) {
+ return sGLContextProviderEGL.CreateForCompositorWidget(
+ aCompositorWidget, aHardwareWebRender, aForceAccelerated);
+#ifdef MOZ_X11
+ } else {
+ return sGLContextProviderGLX.CreateForCompositorWidget(
+ aCompositorWidget, aHardwareWebRender, aForceAccelerated);
+#endif
+ }
+}
+
+/*static*/
+already_AddRefed<GLContext> GLContextProviderLinux::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ if (gfxVars::UseEGL()) {
+ return sGLContextProviderEGL.CreateHeadless(desc, out_failureId);
+#ifdef MOZ_X11
+ } else {
+ return sGLContextProviderGLX.CreateHeadless(desc, out_failureId);
+#endif
+ }
+}
+
+/*static*/
+GLContext* GLContextProviderLinux::GetGlobalContext() {
+ if (gfxVars::UseEGL()) {
+ return sGLContextProviderEGL.GetGlobalContext();
+#ifdef MOZ_X11
+ } else {
+ return sGLContextProviderGLX.GetGlobalContext();
+#endif
+ }
+}
+
+/*static*/
+void GLContextProviderLinux::Shutdown() {
+ if (gfxVars::UseEGL()) {
+ sGLContextProviderEGL.Shutdown();
+#ifdef MOZ_X11
+ } else {
+ sGLContextProviderGLX.Shutdown();
+#endif
+ }
+}
+
+} // namespace mozilla::gl
diff --git a/gfx/gl/GLContextProviderNull.cpp b/gfx/gl/GLContextProviderNull.cpp
new file mode 100644
index 0000000000..558abed19f
--- /dev/null
+++ b/gfx/gl/GLContextProviderNull.cpp
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContextProvider.h"
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::widget;
+
+already_AddRefed<GLContext> GLContextProviderNull::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ return nullptr;
+}
+
+already_AddRefed<GLContext> GLContextProviderNull::CreateHeadless(
+ const GLContextCreateDesc&, nsACString* const out_failureId) {
+ *out_failureId = "FEATURE_FAILURE_NULL"_ns;
+ return nullptr;
+}
+
+GLContext* GLContextProviderNull::GetGlobalContext() { return nullptr; }
+
+void GLContextProviderNull::Shutdown() {}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContextProviderWGL.cpp b/gfx/gl/GLContextProviderWGL.cpp
new file mode 100644
index 0000000000..9786e31307
--- /dev/null
+++ b/gfx/gl/GLContextProviderWGL.cpp
@@ -0,0 +1,529 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContextProvider.h"
+#include "GLContextWGL.h"
+#include "GLLibraryLoader.h"
+#include "nsDebug.h"
+#include "nsIWidget.h"
+#include "gfxPlatform.h"
+#include "gfxWindowsSurface.h"
+
+#include "gfxCrashReporterUtils.h"
+
+#include "prenv.h"
+
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/StaticPrefs_gl.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/layers/CompositorOptions.h"
+#include "mozilla/widget/CompositorWidget.h"
+#include "mozilla/widget/WinCompositorWidget.h"
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::widget;
+
+WGLLibrary sWGLLib;
+
+/*
+ScopedWindow::~ScopedWindow()
+{
+ if (mDC) {
+ MOZ_ALWAYS_TRUE( ReleaseDC(mDC) );
+ }
+ if (mWindow) {
+ MOZ_ALWAYS_TRUE( DestroyWindow(mWindow) );
+ }
+}
+*/
+static HWND CreateDummyWindow() {
+ WNDCLASSW wc{};
+ if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) {
+ wc = {};
+ wc.style = CS_OWNDC;
+ wc.hInstance = GetModuleHandle(nullptr);
+ wc.lpfnWndProc = DefWindowProc;
+ wc.lpszClassName = L"GLContextWGLClass";
+ if (!RegisterClassW(&wc)) {
+ NS_WARNING("Failed to register GLContextWGLClass?!");
+ // er. failed to register our class?
+ return nullptr;
+ }
+ }
+
+ return CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, 0, 0, 1, 1,
+ nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
+}
+
+static inline bool HasExtension(const char* aExtensions,
+ const char* aRequiredExtension) {
+ return GLContext::ListHasExtension(
+ reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
+}
+
+SymbolLoader WGLLibrary::GetSymbolLoader() const {
+ auto ret = SymbolLoader(*mOGLLibrary);
+ ret.mPfn = SymbolLoader::GetProcAddressT(mSymbols.fGetProcAddress);
+ return ret;
+}
+
+bool WGLLibrary::EnsureInitialized() {
+ if (mInitialized) return true;
+
+ mozilla::ScopedGfxFeatureReporter reporter("WGL");
+
+ std::wstring libGLFilename = L"Opengl32.dll";
+ // SU_SPIES_DIRECTORY is for AMD CodeXL/gDEBugger
+ if (_wgetenv(L"SU_SPIES_DIRECTORY")) {
+ libGLFilename =
+ std::wstring(_wgetenv(L"SU_SPIES_DIRECTORY")) + L"\\opengl32.dll";
+ }
+
+ if (!mOGLLibrary) {
+ mOGLLibrary = LoadLibraryWithFlags(libGLFilename.c_str());
+ if (!mOGLLibrary) {
+ NS_WARNING("Couldn't load OpenGL library.");
+ return false;
+ }
+ }
+
+#define SYMBOL(X) \
+ { \
+ (PRFuncPtr*)&mSymbols.f##X, { \
+ { "wgl" #X } \
+ } \
+ }
+#define END_OF_SYMBOLS \
+ { \
+ nullptr, {} \
+ }
+
+ {
+ const auto loader = SymbolLoader(*mOGLLibrary);
+ const SymLoadStruct earlySymbols[] = {SYMBOL(CreateContext),
+ SYMBOL(MakeCurrent),
+ SYMBOL(GetProcAddress),
+ SYMBOL(DeleteContext),
+ SYMBOL(GetCurrentContext),
+ SYMBOL(GetCurrentDC),
+ END_OF_SYMBOLS};
+
+ if (!loader.LoadSymbols(earlySymbols)) {
+ NS_WARNING(
+ "Couldn't find required entry points in OpenGL DLL (early init)");
+ return false;
+ }
+ }
+
+ mDummyWindow = CreateDummyWindow();
+ MOZ_ASSERT(mDummyWindow);
+ if (!mDummyWindow) return false;
+ auto cleanup = MakeScopeExit([&]() { Reset(); });
+
+ mRootDc = GetDC(mDummyWindow);
+ MOZ_ASSERT(mRootDc);
+ if (!mRootDc) return false;
+
+ // --
+
+ {
+ PIXELFORMATDESCRIPTOR pfd{};
+ pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+ // pfd.iPixelType = PFD_TYPE_RGBA;
+ // pfd.cColorBits = 24;
+ // pfd.cRedBits = 8;
+ // pfd.cGreenBits = 8;
+ // pfd.cBlueBits = 8;
+ // pfd.cAlphaBits = 8;
+ pfd.iLayerType = PFD_MAIN_PLANE;
+
+ const auto pixelFormat = ChoosePixelFormat(mRootDc, &pfd);
+ MOZ_ASSERT(pixelFormat);
+ if (!pixelFormat) return false;
+ const bool setPixelFormatOk = SetPixelFormat(mRootDc, pixelFormat, nullptr);
+ MOZ_ASSERT(setPixelFormatOk);
+ if (!setPixelFormatOk) return false;
+ }
+
+ // --
+
+ // create rendering context
+ mDummyGlrc = mSymbols.fCreateContext(mRootDc);
+ if (!mDummyGlrc) return false;
+
+ const auto curCtx = mSymbols.fGetCurrentContext();
+ const auto curDC = mSymbols.fGetCurrentDC();
+
+ GLContext::ResetTLSCurrentContext();
+
+ if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) {
+ NS_WARNING("wglMakeCurrent failed");
+ return false;
+ }
+ const auto resetContext = MakeScopeExit([&]() {
+ GLContext::ResetTLSCurrentContext();
+ mSymbols.fMakeCurrent(curDC, curCtx);
+ });
+
+ const auto loader = GetSymbolLoader();
+
+ // Now we can grab all the other symbols that we couldn't without having
+ // a context current.
+ // clang-format off
+ const SymLoadStruct reqExtSymbols[] = {
+ { (PRFuncPtr*)&mSymbols.fCreatePbuffer, {{ "wglCreatePbufferARB", "wglCreatePbufferEXT" }} },
+ { (PRFuncPtr*)&mSymbols.fDestroyPbuffer, {{ "wglDestroyPbufferARB", "wglDestroyPbufferEXT" }} },
+ { (PRFuncPtr*)&mSymbols.fGetPbufferDC, {{ "wglGetPbufferDCARB", "wglGetPbufferDCEXT" }} },
+ { (PRFuncPtr*)&mSymbols.fReleasePbufferDC, {{ "wglReleasePbufferDCARB", "wglReleasePbufferDCEXT" }} },
+ // { (PRFuncPtr*)&mSymbols.fBindTexImage, {{ "wglBindTexImageARB", "wglBindTexImageEXT" }} },
+ // { (PRFuncPtr*)&mSymbols.fReleaseTexImage, {{ "wglReleaseTexImageARB", "wglReleaseTexImageEXT" }} },
+ { (PRFuncPtr*)&mSymbols.fChoosePixelFormat, {{ "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT" }} },
+ // { (PRFuncPtr*)&mSymbols.fGetPixelFormatAttribiv, {{ "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT" }} },
+ SYMBOL(GetExtensionsStringARB),
+ END_OF_SYMBOLS
+ };
+ // clang-format on
+ if (!loader.LoadSymbols(reqExtSymbols)) {
+ NS_WARNING("reqExtSymbols missing");
+ return false;
+ }
+
+ // --
+
+ const auto extString = mSymbols.fGetExtensionsStringARB(mRootDc);
+ MOZ_ASSERT(extString);
+
+ // --
+
+ if (HasExtension(extString, "WGL_ARB_create_context")) {
+ const SymLoadStruct createContextSymbols[] = {
+ SYMBOL(CreateContextAttribsARB), END_OF_SYMBOLS};
+ if (loader.LoadSymbols(createContextSymbols)) {
+ if (HasExtension(extString, "WGL_ARB_create_context_robustness")) {
+ mHasRobustness = true;
+ }
+ } else {
+ NS_ERROR(
+ "WGL_ARB_create_context announced without supplying its functions.");
+ ClearSymbols(createContextSymbols);
+ }
+ }
+
+ // --
+
+ bool hasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2");
+ if (gfxVars::DXInterop2Blocked() &&
+ !StaticPrefs::gl_ignore_dx_interop2_blacklist()) {
+ hasDXInterop2 = false;
+ }
+
+ if (hasDXInterop2) {
+ const SymLoadStruct dxInteropSymbols[] = {
+ SYMBOL(DXSetResourceShareHandleNV),
+ SYMBOL(DXOpenDeviceNV),
+ SYMBOL(DXCloseDeviceNV),
+ SYMBOL(DXRegisterObjectNV),
+ SYMBOL(DXUnregisterObjectNV),
+ SYMBOL(DXObjectAccessNV),
+ SYMBOL(DXLockObjectsNV),
+ SYMBOL(DXUnlockObjectsNV),
+ END_OF_SYMBOLS};
+ if (!loader.LoadSymbols(dxInteropSymbols)) {
+ NS_ERROR(
+ "WGL_NV_DX_interop2 announceed without supplying its functions.");
+ ClearSymbols(dxInteropSymbols);
+ }
+ }
+
+ // --
+
+ cleanup.release();
+
+ mInitialized = true;
+
+ reporter.SetSuccessful();
+ return true;
+}
+
+#undef SYMBOL
+#undef END_OF_SYMBOLS
+
+void WGLLibrary::Reset() {
+ if (mDummyGlrc) {
+ (void)mSymbols.fDeleteContext(mDummyGlrc);
+ mDummyGlrc = nullptr;
+ }
+ if (mRootDc) {
+ (void)ReleaseDC(mDummyWindow, mRootDc);
+ mRootDc = nullptr;
+ }
+ if (mDummyWindow) {
+ (void)DestroyWindow(mDummyWindow);
+ mDummyWindow = nullptr;
+ }
+}
+
+GLContextWGL::GLContextWGL(const GLContextDesc& desc, HDC aDC, HGLRC aContext,
+ HWND aWindow)
+ : GLContext(desc, nullptr, false),
+ mDC(aDC),
+ mContext(aContext),
+ mWnd(aWindow),
+ mPBuffer(nullptr),
+ mPixelFormat(0) {}
+
+GLContextWGL::GLContextWGL(const GLContextDesc& desc, HANDLE aPbuffer, HDC aDC,
+ HGLRC aContext, int aPixelFormat)
+ : GLContext(desc, nullptr, false),
+ mDC(aDC),
+ mContext(aContext),
+ mWnd(nullptr),
+ mPBuffer(aPbuffer),
+ mPixelFormat(aPixelFormat) {}
+
+GLContextWGL::~GLContextWGL() {
+ MarkDestroyed();
+
+ (void)sWGLLib.mSymbols.fDeleteContext(mContext);
+
+ if (mPBuffer) {
+ (void)sWGLLib.mSymbols.fReleasePbufferDC(mPBuffer, mDC);
+ (void)sWGLLib.mSymbols.fDestroyPbuffer(mPBuffer);
+ }
+ if (mWnd) {
+ (void)ReleaseDC(mWnd, mDC);
+ DestroyWindow(mWnd);
+ }
+}
+
+bool GLContextWGL::MakeCurrentImpl() const {
+ GLContext::ResetTLSCurrentContext();
+
+ const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
+ NS_ASSERTION(succeeded, "Failed to make GL context current!");
+ return succeeded;
+}
+
+bool GLContextWGL::IsCurrentImpl() const {
+ return sWGLLib.mSymbols.fGetCurrentContext() == mContext;
+}
+
+bool GLContextWGL::SwapBuffers() {
+ if (!mIsDoubleBuffered) return false;
+ return ::SwapBuffers(mDC);
+}
+
+void GLContextWGL::GetWSIInfo(nsCString* const out) const {
+ out->AppendLiteral("wglGetExtensionsString: ");
+ out->Append(sWGLLib.mSymbols.fGetExtensionsStringARB(mDC));
+}
+
+HGLRC
+WGLLibrary::CreateContextWithFallback(const HDC dc,
+ const bool tryRobustBuffers) const {
+ if (mHasRobustness) {
+ if (tryRobustBuffers) {
+ const int attribs[] = {LOCAL_WGL_CONTEXT_FLAGS_ARB,
+ LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
+ LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
+ const auto context =
+ mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
+ if (context) return context;
+ }
+
+ const int attribs[] = {LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB, 0};
+ const auto context =
+ mSymbols.fCreateContextAttribsARB(dc, nullptr, attribs);
+ if (context) return context;
+ }
+ if (mSymbols.fCreateContextAttribsARB) {
+ const auto context =
+ mSymbols.fCreateContextAttribsARB(dc, nullptr, nullptr);
+ if (context) return context;
+ }
+ return mSymbols.fCreateContext(dc);
+}
+
+static RefPtr<GLContext> CreateForWidget(const HWND window,
+ const bool isWebRender,
+ const bool requireAccelerated) {
+ auto& wgl = sWGLLib;
+ if (!wgl.EnsureInitialized()) return nullptr;
+
+ const auto dc = GetDC(window);
+ if (!dc) return nullptr;
+ auto cleanupDc = MakeScopeExit([&]() { (void)ReleaseDC(window, dc); });
+
+ int chosenFormat;
+ UINT foundFormats = 0;
+
+ if (!foundFormats) {
+ const int kAttribs[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
+ true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB,
+ true,
+ LOCAL_WGL_DOUBLE_BUFFER_ARB,
+ true,
+ LOCAL_WGL_ACCELERATION_ARB,
+ LOCAL_WGL_FULL_ACCELERATION_ARB,
+ 0};
+ const int kAttribsForWebRender[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
+ true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB,
+ true,
+ LOCAL_WGL_DOUBLE_BUFFER_ARB,
+ true,
+ LOCAL_WGL_DEPTH_BITS_ARB,
+ 24,
+ LOCAL_WGL_ACCELERATION_ARB,
+ LOCAL_WGL_FULL_ACCELERATION_ARB,
+ 0};
+ const int* attribs;
+ if (isWebRender) {
+ attribs = kAttribsForWebRender;
+ } else {
+ attribs = kAttribs;
+ }
+
+ if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), attribs, nullptr, 1,
+ &chosenFormat, &foundFormats)) {
+ foundFormats = 0;
+ }
+ }
+ if (!foundFormats) {
+ if (requireAccelerated) return nullptr;
+
+ const int kAttribs[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
+ true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB,
+ true,
+ LOCAL_WGL_DOUBLE_BUFFER_ARB,
+ true,
+ 0};
+ const int kAttribsForWebRender[] = {LOCAL_WGL_DRAW_TO_WINDOW_ARB,
+ true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB,
+ true,
+ LOCAL_WGL_DOUBLE_BUFFER_ARB,
+ true,
+ LOCAL_WGL_DEPTH_BITS_ARB,
+ 24,
+ 0};
+
+ const int* attribs;
+ if (isWebRender) {
+ attribs = kAttribsForWebRender;
+ } else {
+ attribs = kAttribs;
+ }
+
+ if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), attribs, nullptr, 1,
+ &chosenFormat, &foundFormats)) {
+ foundFormats = 0;
+ }
+ }
+ if (!foundFormats) return nullptr;
+
+ // We need to make sure we call SetPixelFormat -after- calling
+ // EnsureInitialized, otherwise it can load/unload the dll and
+ // wglCreateContext will fail.
+
+ SetPixelFormat(dc, chosenFormat, nullptr);
+ const auto context = sWGLLib.CreateContextWithFallback(dc, false);
+ if (!context) return nullptr;
+
+ const RefPtr<GLContextWGL> gl = new GLContextWGL({}, dc, context);
+ cleanupDc.release();
+ gl->mIsDoubleBuffered = true;
+ if (!gl->Init()) return nullptr;
+
+ return gl;
+}
+
+already_AddRefed<GLContext> GLContextProviderWGL::CreateForCompositorWidget(
+ CompositorWidget* aCompositorWidget, bool aHardwareWebRender,
+ bool aForceAccelerated) {
+ if (!aCompositorWidget) {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+ return CreateForWidget(aCompositorWidget->AsWindows()->GetHwnd(),
+ aHardwareWebRender, aForceAccelerated)
+ .forget();
+}
+
+/*static*/
+already_AddRefed<GLContext> GLContextProviderWGL::CreateHeadless(
+ const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+ auto& wgl = sWGLLib;
+ if (!wgl.EnsureInitialized()) return nullptr;
+
+ int chosenFormat;
+ UINT foundFormats = 0;
+
+ if (!foundFormats) {
+ const int kAttribs[] = {LOCAL_WGL_DRAW_TO_PBUFFER_ARB,
+ true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB,
+ true,
+ LOCAL_WGL_ACCELERATION_ARB,
+ LOCAL_WGL_FULL_ACCELERATION_ARB,
+ 0};
+ if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+ &chosenFormat, &foundFormats)) {
+ foundFormats = 0;
+ }
+ }
+ if (!foundFormats) {
+ const int kAttribs[] = {LOCAL_WGL_DRAW_TO_PBUFFER_ARB, true,
+ LOCAL_WGL_SUPPORT_OPENGL_ARB, true, 0};
+ if (!wgl.mSymbols.fChoosePixelFormat(wgl.RootDc(), kAttribs, nullptr, 1,
+ &chosenFormat, &foundFormats)) {
+ foundFormats = 0;
+ }
+ }
+ if (!foundFormats) return nullptr;
+ const int kPbufferAttribs[] = {0};
+ const auto pbuffer = wgl.mSymbols.fCreatePbuffer(wgl.RootDc(), chosenFormat,
+ 1, 1, kPbufferAttribs);
+ if (!pbuffer) return nullptr;
+ auto cleanupPbuffer =
+ MakeScopeExit([&]() { (void)wgl.mSymbols.fDestroyPbuffer(pbuffer); });
+
+ const auto dc = wgl.mSymbols.fGetPbufferDC(pbuffer);
+ if (!dc) return nullptr;
+ auto cleanupDc = MakeScopeExit(
+ [&]() { (void)wgl.mSymbols.fReleasePbufferDC(pbuffer, dc); });
+
+ const auto context = wgl.CreateContextWithFallback(dc, true);
+ if (!context) return nullptr;
+
+ const auto fullDesc = GLContextDesc{desc, true};
+ const RefPtr<GLContextWGL> gl =
+ new GLContextWGL(fullDesc, pbuffer, dc, context, chosenFormat);
+ cleanupPbuffer.release();
+ cleanupDc.release();
+ if (!gl->Init()) return nullptr;
+
+ return RefPtr<GLContext>(gl.get()).forget();
+}
+
+/*static*/
+GLContext* GLContextProviderWGL::GetGlobalContext() { return nullptr; }
+
+/*static*/
+void GLContextProviderWGL::Shutdown() {}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLContextSymbols.h b/gfx/gl/GLContextSymbols.h
new file mode 100644
index 0000000000..ac74f32e14
--- /dev/null
+++ b/gfx/gl/GLContextSymbols.h
@@ -0,0 +1,467 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTSYMBOLS_H_
+#define GLCONTEXTSYMBOLS_H_
+
+#include "GLDefs.h"
+
+/*
+ * This file should only be included by GLContext.h, and should be
+ * autogenerated in the future.
+ */
+
+#ifndef GLAPIENTRY
+# ifdef XP_WIN
+# define GLAPIENTRY __stdcall
+# else
+# define GLAPIENTRY
+# endif
+# define GLAPI
+#endif
+
+namespace mozilla {
+namespace gl {
+
+struct GLContextSymbols final {
+ void(GLAPIENTRY* fActiveTexture)(GLenum);
+ void(GLAPIENTRY* fAttachShader)(GLuint, GLuint);
+ void(GLAPIENTRY* fBeginQuery)(GLenum, GLuint);
+ void(GLAPIENTRY* fBindAttribLocation)(GLuint, GLuint, const GLchar*);
+ void(GLAPIENTRY* fBindBuffer)(GLenum, GLuint);
+ void(GLAPIENTRY* fBindTexture)(GLenum, GLuint);
+ void(GLAPIENTRY* fBindVertexArray)(GLuint);
+ void(GLAPIENTRY* fBlendColor)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fBlendEquation)(GLenum);
+ void(GLAPIENTRY* fBlendEquationSeparate)(GLenum, GLenum);
+ void(GLAPIENTRY* fBlendFunc)(GLenum, GLenum);
+ void(GLAPIENTRY* fBlendFuncSeparate)(GLenum, GLenum, GLenum, GLenum);
+ void(GLAPIENTRY* fBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum);
+ void(GLAPIENTRY* fBufferSubData)(GLenum, GLintptr, GLsizeiptr, const GLvoid*);
+
+ void(GLAPIENTRY* fClear)(GLbitfield);
+ void(GLAPIENTRY* fClearBufferfi)(GLenum, GLint, GLfloat, GLint);
+ void(GLAPIENTRY* fClearBufferfv)(GLenum, GLint, const GLfloat*);
+ void(GLAPIENTRY* fClearBufferiv)(GLenum, GLint, const GLint*);
+ void(GLAPIENTRY* fClearBufferuiv)(GLenum, GLint, const GLuint*);
+ void(GLAPIENTRY* fClearColor)(GLfloat, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fClearStencil)(GLint);
+ void(GLAPIENTRY* fColorMask)(realGLboolean, realGLboolean, realGLboolean,
+ realGLboolean);
+ void(GLAPIENTRY* fCompressedTexImage2D)(GLenum, GLint, GLenum, GLsizei,
+ GLsizei, GLint, GLsizei,
+ const GLvoid*);
+ void(GLAPIENTRY* fCompressedTexSubImage2D)(GLenum, GLint, GLint, GLint,
+ GLsizei, GLsizei, GLenum, GLsizei,
+ const GLvoid*);
+ void(GLAPIENTRY* fCullFace)(GLenum);
+ void(GLAPIENTRY* fDetachShader)(GLuint, GLuint);
+ void(GLAPIENTRY* fDepthFunc)(GLenum);
+ void(GLAPIENTRY* fDepthMask)(realGLboolean);
+ void(GLAPIENTRY* fDisable)(GLenum);
+ void(GLAPIENTRY* fDisableVertexAttribArray)(GLuint);
+ void(GLAPIENTRY* fDrawArrays)(GLenum, GLint, GLsizei);
+ void(GLAPIENTRY* fDrawBuffer)(GLenum);
+ void(GLAPIENTRY* fDrawBuffers)(GLsizei, const GLenum*);
+ void(GLAPIENTRY* fDrawElements)(GLenum, GLsizei, GLenum, const GLvoid*);
+ void(GLAPIENTRY* fEnable)(GLenum);
+ void(GLAPIENTRY* fEnableVertexAttribArray)(GLuint);
+ void(GLAPIENTRY* fFinish)(void);
+ void(GLAPIENTRY* fEndQuery)(GLenum);
+ void(GLAPIENTRY* fFlush)(void);
+ void(GLAPIENTRY* fFrontFace)(GLenum);
+ void(GLAPIENTRY* fGetActiveAttrib)(GLuint, GLuint, GLsizei, GLsizei*, GLint*,
+ GLenum*, GLchar*);
+ void(GLAPIENTRY* fGetActiveUniform)(GLuint, GLuint, GLsizei, GLsizei*, GLint*,
+ GLenum*, GLchar*);
+ void(GLAPIENTRY* fGetAttachedShaders)(GLuint, GLsizei, GLsizei*, GLuint*);
+ GLint(GLAPIENTRY* fGetAttribLocation)(GLuint, const GLchar*);
+ void(GLAPIENTRY* fGetIntegerv)(GLenum, GLint*);
+ void(GLAPIENTRY* fGetFloatv)(GLenum, GLfloat*);
+ void(GLAPIENTRY* fGetBooleanv)(GLenum, realGLboolean*);
+ void(GLAPIENTRY* fGetBufferParameteriv)(GLenum, GLenum, GLint*);
+ void(GLAPIENTRY* fGenerateMipmap)(GLenum);
+ GLenum(GLAPIENTRY* fGetError)(void);
+ void(GLAPIENTRY* fGetProgramiv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetProgramInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
+ void(GLAPIENTRY* fGetQueryiv)(GLenum, GLenum, GLint*);
+ void(GLAPIENTRY* fGetQueryObjectiv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetQueryObjectuiv)(GLuint, GLenum, GLuint*);
+ void(GLAPIENTRY* fGetQueryObjecti64v)(GLuint, GLenum, GLint64*);
+ void(GLAPIENTRY* fGetQueryObjectui64v)(GLuint, GLenum, GLuint64*);
+ void(GLAPIENTRY* fQueryCounter)(GLuint, GLenum);
+ void(GLAPIENTRY* fTexParameteri)(GLenum, GLenum, GLint);
+ void(GLAPIENTRY* fTexParameteriv)(GLenum, GLenum, const GLint*);
+ void(GLAPIENTRY* fTexParameterf)(GLenum, GLenum, GLfloat);
+ GLubyte*(GLAPIENTRY* fGetString)(GLenum);
+ void(GLAPIENTRY* fGetTexImage)(GLenum, GLint, GLenum, GLenum, GLvoid*);
+ void(GLAPIENTRY* fGetTexLevelParameteriv)(GLenum, GLint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetTexParameterfv)(GLenum, GLenum, GLfloat*);
+ void(GLAPIENTRY* fGetTexParameteriv)(GLenum, GLenum, GLint*);
+ void(GLAPIENTRY* fGetUniformfv)(GLuint, GLint, GLfloat*);
+ void(GLAPIENTRY* fGetUniformiv)(GLuint, GLint, GLint*);
+ void(GLAPIENTRY* fGetUniformuiv)(GLuint, GLint, GLuint*);
+ GLint(GLAPIENTRY* fGetUniformLocation)(GLuint, const GLchar*);
+ void(GLAPIENTRY* fGetVertexAttribfv)(GLuint, GLenum, GLfloat*);
+ void(GLAPIENTRY* fGetVertexAttribiv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetVertexAttribPointerv)(GLuint, GLenum, GLvoid**);
+ void(GLAPIENTRY* fHint)(GLenum, GLenum);
+ realGLboolean(GLAPIENTRY* fIsBuffer)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsEnabled)(GLenum);
+ realGLboolean(GLAPIENTRY* fIsProgram)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsQuery)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsShader)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsTexture)(GLuint);
+ void(GLAPIENTRY* fLineWidth)(GLfloat);
+ void(GLAPIENTRY* fLinkProgram)(GLuint);
+ void(GLAPIENTRY* fPixelStorei)(GLenum, GLint);
+ void(GLAPIENTRY* fPointParameterf)(GLenum, GLfloat);
+ void(GLAPIENTRY* fPolygonMode)(GLenum, GLenum);
+ void(GLAPIENTRY* fPolygonOffset)(GLfloat, GLfloat);
+ void(GLAPIENTRY* fReadBuffer)(GLenum);
+ void(GLAPIENTRY* fReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum,
+ GLvoid*);
+ void(GLAPIENTRY* fSampleCoverage)(GLclampf, realGLboolean);
+ void(GLAPIENTRY* fStencilFunc)(GLenum, GLint, GLuint);
+ void(GLAPIENTRY* fStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint);
+ void(GLAPIENTRY* fStencilMask)(GLuint);
+ void(GLAPIENTRY* fStencilMaskSeparate)(GLenum, GLuint);
+ void(GLAPIENTRY* fStencilOp)(GLenum, GLenum, GLenum);
+ void(GLAPIENTRY* fStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum);
+ void(GLAPIENTRY* fTexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint,
+ GLenum, GLenum, const GLvoid*);
+ void(GLAPIENTRY* fTexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei,
+ GLsizei, GLenum, GLenum, const void*);
+ void(GLAPIENTRY* fTextureRangeAPPLE)(GLenum, GLsizei, GLvoid*);
+ void(GLAPIENTRY* fFinishObjectAPPLE)(GLenum, GLint);
+ realGLboolean(GLAPIENTRY* fTestObjectAPPLE)(GLenum, GLint);
+ void(GLAPIENTRY* fUniform1f)(GLint, GLfloat);
+ void(GLAPIENTRY* fUniform1fv)(GLint, GLsizei, const GLfloat*);
+ void(GLAPIENTRY* fUniform1i)(GLint, GLint);
+ void(GLAPIENTRY* fUniform1iv)(GLint, GLsizei, const GLint*);
+ void(GLAPIENTRY* fUniform2f)(GLint, GLfloat, GLfloat);
+ void(GLAPIENTRY* fUniform2fv)(GLint, GLsizei, const GLfloat*);
+ void(GLAPIENTRY* fUniform2i)(GLint, GLint, GLint);
+ void(GLAPIENTRY* fUniform2iv)(GLint, GLsizei, const GLint*);
+ void(GLAPIENTRY* fUniform3f)(GLint, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fUniform3fv)(GLint, GLsizei, const GLfloat*);
+ void(GLAPIENTRY* fUniform3i)(GLint, GLint, GLint, GLint);
+ void(GLAPIENTRY* fUniform3iv)(GLint, GLsizei, const GLint*);
+ void(GLAPIENTRY* fUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fUniform4fv)(GLint, GLsizei, const GLfloat*);
+ void(GLAPIENTRY* fUniform4i)(GLint, GLint, GLint, GLint, GLint);
+ void(GLAPIENTRY* fUniform4iv)(GLint, GLsizei, const GLint*);
+ void(GLAPIENTRY* fUniformMatrix2fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix2x3fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix2x4fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix3fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix3x2fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix3x4fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix4fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix4x2fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+ void(GLAPIENTRY* fUniformMatrix4x3fv)(GLint, GLsizei, realGLboolean,
+ const GLfloat*);
+
+ void(GLAPIENTRY* fUseProgram)(GLuint);
+ void(GLAPIENTRY* fValidateProgram)(GLuint);
+ void(GLAPIENTRY* fVertexAttribPointer)(GLuint, GLint, GLenum, realGLboolean,
+ GLsizei, const GLvoid*);
+ void(GLAPIENTRY* fVertexAttrib1f)(GLuint, GLfloat);
+ void(GLAPIENTRY* fVertexAttrib2f)(GLuint, GLfloat, GLfloat);
+ void(GLAPIENTRY* fVertexAttrib3f)(GLuint, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fVertexAttrib4f)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat);
+ void(GLAPIENTRY* fVertexAttrib1fv)(GLuint, const GLfloat*);
+ void(GLAPIENTRY* fVertexAttrib2fv)(GLuint, const GLfloat*);
+ void(GLAPIENTRY* fVertexAttrib3fv)(GLuint, const GLfloat*);
+ void(GLAPIENTRY* fVertexAttrib4fv)(GLuint, const GLfloat*);
+ void(GLAPIENTRY* fCompileShader)(GLuint);
+ void(GLAPIENTRY* fCopyTexImage2D)(GLenum, GLint, GLenum, GLint, GLint,
+ GLsizei, GLsizei, GLint);
+ void(GLAPIENTRY* fCopyTexSubImage2D)(GLenum, GLint, GLint, GLint, GLint,
+ GLint, GLsizei, GLsizei);
+ void(GLAPIENTRY* fGetShaderiv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetShaderInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*);
+ void(GLAPIENTRY* fGetShaderPrecisionFormat)(GLenum, GLenum, GLint*, GLint*);
+ void(GLAPIENTRY* fGetShaderSource)(GLint, GLsizei, GLsizei*, GLchar*);
+ void(GLAPIENTRY* fShaderSource)(GLuint, GLsizei, const GLchar* const*,
+ const GLint*);
+
+ void(GLAPIENTRY* fBindFramebuffer)(GLenum, GLuint);
+ void(GLAPIENTRY* fBindRenderbuffer)(GLenum, GLuint);
+ GLenum(GLAPIENTRY* fCheckFramebufferStatus)(GLenum);
+ void(GLAPIENTRY* fFramebufferRenderbuffer)(GLenum, GLenum, GLenum, GLuint);
+ void(GLAPIENTRY* fFramebufferTexture2D)(GLenum, GLenum, GLenum, GLuint,
+ GLint);
+ void(GLAPIENTRY* fFramebufferTextureLayer)(GLenum, GLenum, GLuint, GLint,
+ GLint);
+ void(GLAPIENTRY* fGetFramebufferAttachmentParameteriv)(GLenum, GLenum, GLenum,
+ GLint*);
+ void(GLAPIENTRY* fGetRenderbufferParameteriv)(GLenum, GLenum, GLint*);
+ realGLboolean(GLAPIENTRY* fIsFramebuffer)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsRenderbuffer)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsVertexArray)(GLuint);
+ void(GLAPIENTRY* fRenderbufferStorage)(GLenum, GLenum, GLsizei, GLsizei);
+
+ void(GLAPIENTRY* fInvalidateFramebuffer)(GLenum, GLsizei, const GLenum*);
+ void(GLAPIENTRY* fInvalidateSubFramebuffer)(GLenum, GLsizei, const GLenum*,
+ GLint, GLint, GLsizei, GLsizei);
+
+ // These functions are only used by Skia/GL in desktop mode.
+ // Other parts of Gecko should avoid using these
+ void(GLAPIENTRY* fClientActiveTexture)(GLenum);
+ void(GLAPIENTRY* fDisableClientState)(GLenum);
+ void(GLAPIENTRY* fEnableClientState)(GLenum);
+ void(GLAPIENTRY* fLoadIdentity)(void);
+ void(GLAPIENTRY* fLoadMatrixd)(const GLdouble*);
+ void(GLAPIENTRY* fLoadMatrixf)(const GLfloat*);
+ void(GLAPIENTRY* fMatrixMode)(GLenum);
+ void(GLAPIENTRY* fTexGeni)(GLenum, GLenum, GLint);
+ void(GLAPIENTRY* fTexGenf)(GLenum, GLenum, GLfloat);
+ void(GLAPIENTRY* fTexGenfv)(GLenum, GLenum, const GLfloat*);
+ void(GLAPIENTRY* fVertexPointer)(GLint, GLenum, GLsizei, const GLvoid*);
+
+ void(GLAPIENTRY* fBlitFramebuffer)(GLint, GLint, GLint, GLint, GLint, GLint,
+ GLint, GLint, GLbitfield, GLenum);
+ void(GLAPIENTRY* fRenderbufferStorageMultisample)(GLenum, GLsizei, GLenum,
+ GLsizei, GLsizei);
+
+ /* These are different between GLES2 and desktop GL; we hide those
+ * differences, use the GL names, but the most limited data type.
+ */
+ void(GLAPIENTRY* fDepthRangef)(GLclampf, GLclampf);
+ void(GLAPIENTRY* fClearDepthf)(GLclampf);
+
+ void(GLAPIENTRY* fDepthRange)(GLclampd, GLclampd);
+ void(GLAPIENTRY* fClearDepth)(GLclampd);
+
+ /* These are special because we end up tracking these so that we don't
+ * have to query the values from GL.
+ */
+
+ void(GLAPIENTRY* fViewport)(GLint, GLint, GLsizei, GLsizei);
+ void(GLAPIENTRY* fScissor)(GLint, GLint, GLsizei, GLsizei);
+
+ /* These are special -- they create or delete GL resources that can live
+ * in a shared namespace. In DEBUG, we wrap these calls so that we can
+ * check when we have something that failed to do cleanup at the time the
+ * final context is destroyed.
+ */
+
+ GLuint(GLAPIENTRY* fCreateProgram)();
+ GLuint(GLAPIENTRY* fCreateShader)(GLenum);
+ void(GLAPIENTRY* fGenBuffers)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fGenQueries)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fGenTextures)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fGenFramebuffers)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fGenRenderbuffers)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fGenVertexArrays)(GLsizei, GLuint*);
+
+ void(GLAPIENTRY* fDeleteProgram)(GLuint);
+ void(GLAPIENTRY* fDeleteShader)(GLuint);
+ void(GLAPIENTRY* fDeleteBuffers)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fDeleteQueries)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fDeleteTextures)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fDeleteFramebuffers)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fDeleteRenderbuffers)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fDeleteVertexArrays)(GLsizei, const GLuint*);
+
+ void*(GLAPIENTRY* fMapBuffer)(GLenum, GLenum);
+ realGLboolean(GLAPIENTRY* fUnmapBuffer)(GLenum);
+
+ // ARB_copy_buffer / OpenGL 3.1 / OpenGL ES 3.0
+ void(GLAPIENTRY* fCopyBufferSubData)(GLenum, GLenum, GLintptr, GLintptr,
+ GLsizeiptr);
+
+ GLenum(GLAPIENTRY* fGetGraphicsResetStatus)();
+
+ // ARB_sync
+ GLsync(GLAPIENTRY* fFenceSync)(GLenum, GLbitfield);
+ realGLboolean(GLAPIENTRY* fIsSync)(GLsync);
+ void(GLAPIENTRY* fDeleteSync)(GLsync);
+ GLenum(GLAPIENTRY* fClientWaitSync)(GLsync, GLbitfield, GLuint64);
+ void(GLAPIENTRY* fWaitSync)(GLsync, GLbitfield, GLuint64);
+ void(GLAPIENTRY* fGetInteger64v)(GLenum, GLint64*);
+ void(GLAPIENTRY* fGetSynciv)(GLsync, GLenum, GLsizei, GLsizei*, GLint*);
+
+ // OES_egl_image
+ void(GLAPIENTRY* fEGLImageTargetTexture2D)(GLenum, GLeglImage);
+ void(GLAPIENTRY* fEGLImageTargetRenderbufferStorage)(GLenum, GLeglImage);
+
+ // ARB_draw_instanced
+ void(GLAPIENTRY* fDrawArraysInstanced)(GLenum, GLint, GLsizei, GLsizei);
+ void(GLAPIENTRY* fDrawElementsInstanced)(GLenum, GLsizei, GLenum,
+ const GLvoid*, GLsizei);
+
+ // ARB_instanced_array
+ void(GLAPIENTRY* fVertexAttribDivisor)(GLuint, GLuint);
+
+ // ARB_internalformat_query
+ void(GLAPIENTRY* fGetInternalformativ)(GLenum, GLenum, GLenum, GLsizei,
+ GLint*);
+
+ // ARB_transform_feedback2 / OpenGL 4.0 / OpenGL ES 3.0
+ void(GLAPIENTRY* fBindBufferBase)(GLenum, GLuint, GLuint);
+ void(GLAPIENTRY* fBindBufferRange)(GLenum, GLuint, GLuint, GLintptr,
+ GLsizeiptr);
+
+ void(GLAPIENTRY* fGenTransformFeedbacks)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fDeleteTransformFeedbacks)(GLsizei, const GLuint*);
+ realGLboolean(GLAPIENTRY* fIsTransformFeedback)(GLuint);
+ void(GLAPIENTRY* fBindTransformFeedback)(GLenum, GLuint);
+ void(GLAPIENTRY* fTransformFeedbackVaryings)(GLuint, GLsizei,
+ const GLchar* const*, GLenum);
+ void(GLAPIENTRY* fGetTransformFeedbackVarying)(GLuint, GLuint, GLsizei,
+ GLsizei*, GLsizei*, GLenum*,
+ GLchar*);
+ void(GLAPIENTRY* fBeginTransformFeedback)(GLenum);
+ void(GLAPIENTRY* fEndTransformFeedback)(void);
+ void(GLAPIENTRY* fPauseTransformFeedback)(void);
+ void(GLAPIENTRY* fResumeTransformFeedback)(void);
+
+ void(GLAPIENTRY* fGetIntegeri_v)(GLenum, GLuint, GLint*);
+ void(GLAPIENTRY* fGetInteger64i_v)(GLenum, GLuint, GLint64*);
+
+ // EXT_transform_feedback only
+ void(GLAPIENTRY* fBindBufferOffset)(GLenum, GLuint, GLuint, GLintptr);
+
+ // KHR_debug
+ void(GLAPIENTRY* fDebugMessageControl)(GLenum, GLenum, GLenum, GLsizei,
+ const GLuint*, realGLboolean);
+ void(GLAPIENTRY* fDebugMessageInsert)(GLenum, GLenum, GLuint, GLenum, GLsizei,
+ const GLchar*);
+ void(GLAPIENTRY* fDebugMessageCallback)(GLDEBUGPROC, const GLvoid*);
+ GLuint(GLAPIENTRY* fGetDebugMessageLog)(GLuint, GLsizei, GLenum*, GLenum*,
+ GLuint*, GLenum*, GLsizei*, GLchar*);
+ void(GLAPIENTRY* fGetPointerv)(GLenum, GLvoid**);
+ void(GLAPIENTRY* fPushDebugGroup)(GLenum, GLuint, GLsizei, const GLchar*);
+ void(GLAPIENTRY* fPopDebugGroup)(void);
+ void(GLAPIENTRY* fObjectLabel)(GLenum, GLuint, GLsizei, const GLchar*);
+ void(GLAPIENTRY* fGetObjectLabel)(GLenum, GLuint, GLsizei, GLsizei*, GLchar*);
+ void(GLAPIENTRY* fObjectPtrLabel)(const GLvoid*, GLsizei, const GLchar*);
+ void(GLAPIENTRY* fGetObjectPtrLabel)(const GLvoid*, GLsizei, GLsizei*,
+ GLchar*);
+
+ // NV_fence
+ void(GLAPIENTRY* fGenFences)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fDeleteFences)(GLsizei, const GLuint*);
+ void(GLAPIENTRY* fSetFence)(GLuint, GLenum);
+ realGLboolean(GLAPIENTRY* fTestFence)(GLuint);
+ void(GLAPIENTRY* fFinishFence)(GLuint);
+ realGLboolean(GLAPIENTRY* fIsFence)(GLuint);
+ void(GLAPIENTRY* fGetFenceiv)(GLuint, GLenum, GLint*);
+
+ // map_buffer_range
+ void*(GLAPIENTRY* fMapBufferRange)(GLenum, GLintptr, GLsizeiptr, GLbitfield);
+ void(GLAPIENTRY* fFlushMappedBufferRange)(GLenum, GLintptr, GLsizeiptr);
+
+ // sampler_object
+ void(GLAPIENTRY* fGenSamplers)(GLsizei, GLuint*);
+ void(GLAPIENTRY* fDeleteSamplers)(GLsizei, const GLuint*);
+ realGLboolean(GLAPIENTRY* fIsSampler)(GLuint);
+ void(GLAPIENTRY* fBindSampler)(GLuint, GLuint);
+ void(GLAPIENTRY* fSamplerParameteri)(GLuint, GLenum, GLint);
+ void(GLAPIENTRY* fSamplerParameteriv)(GLuint, GLenum, const GLint*);
+ void(GLAPIENTRY* fSamplerParameterf)(GLuint, GLenum, GLfloat);
+ void(GLAPIENTRY* fSamplerParameterfv)(GLuint, GLenum, const GLfloat*);
+ void(GLAPIENTRY* fGetSamplerParameteriv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetSamplerParameterfv)(GLuint, GLenum, GLfloat*);
+
+ // texture_storage
+ void(GLAPIENTRY* fTexStorage2D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei);
+ void(GLAPIENTRY* fTexStorage3D)(GLenum, GLsizei, GLenum, GLsizei, GLsizei,
+ GLsizei);
+
+ // uniform_buffer_object
+ void(GLAPIENTRY* fGetUniformIndices)(GLuint, GLsizei, const GLchar* const*,
+ GLuint*);
+ void(GLAPIENTRY* fGetActiveUniformsiv)(GLuint, GLsizei, const GLuint*, GLenum,
+ GLint*);
+ GLuint(GLAPIENTRY* fGetUniformBlockIndex)(GLuint, const GLchar*);
+ void(GLAPIENTRY* fGetActiveUniformBlockiv)(GLuint, GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetActiveUniformBlockName)(GLuint, GLuint, GLsizei,
+ GLsizei*, GLchar*);
+ void(GLAPIENTRY* fUniformBlockBinding)(GLuint, GLuint, GLuint);
+
+ // EXT_gpu_shader4
+ void(GLAPIENTRY* fGetVertexAttribIiv)(GLuint, GLenum, GLint*);
+ void(GLAPIENTRY* fGetVertexAttribIuiv)(GLuint, GLenum, GLuint*);
+ void(GLAPIENTRY* fVertexAttribI4i)(GLuint, GLint, GLint, GLint, GLint);
+ void(GLAPIENTRY* fVertexAttribI4iv)(GLuint, const GLint*);
+ void(GLAPIENTRY* fVertexAttribI4ui)(GLuint, GLuint, GLuint, GLuint, GLuint);
+ void(GLAPIENTRY* fVertexAttribI4uiv)(GLuint, const GLuint*);
+ void(GLAPIENTRY* fVertexAttribIPointer)(GLuint, GLint, GLenum, GLsizei,
+ const GLvoid*);
+ void(GLAPIENTRY* fUniform1ui)(GLint, GLuint);
+ void(GLAPIENTRY* fUniform2ui)(GLint, GLuint, GLuint);
+ void(GLAPIENTRY* fUniform3ui)(GLint, GLuint, GLuint, GLuint);
+ void(GLAPIENTRY* fUniform4ui)(GLint, GLuint, GLuint, GLuint, GLuint);
+ void(GLAPIENTRY* fUniform1uiv)(GLint, GLsizei, const GLuint*);
+ void(GLAPIENTRY* fUniform2uiv)(GLint, GLsizei, const GLuint*);
+ void(GLAPIENTRY* fUniform3uiv)(GLint, GLsizei, const GLuint*);
+ void(GLAPIENTRY* fUniform4uiv)(GLint, GLsizei, const GLuint*);
+ GLint(GLAPIENTRY* fGetFragDataLocation)(GLuint, const GLchar*);
+
+ // 3D Textures
+ void(GLAPIENTRY* fTexImage3D)(GLenum, GLint, GLenum, GLenum, GLsizei, GLsizei,
+ GLint, GLenum, GLenum, const GLvoid*);
+
+ void(GLAPIENTRY* fTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei,
+ GLsizei, GLsizei, GLenum, GLenum,
+ const GLvoid*);
+
+ void(GLAPIENTRY* fCopyTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint,
+ GLint, GLint, GLsizei, GLsizei);
+
+ void(GLAPIENTRY* fCompressedTexImage3D)(GLenum, GLint, GLenum, GLsizei,
+ GLsizei, GLsizei, GLint, GLsizei,
+ const GLvoid*);
+
+ void(GLAPIENTRY* fCompressedTexSubImage3D)(GLenum, GLint, GLint, GLint, GLint,
+ GLsizei, GLsizei, GLsizei, GLenum,
+ GLsizei, const GLvoid*);
+
+ // get_string_indexed
+ const GLubyte*(GLAPIENTRY* fGetStringi)(GLenum, GLuint);
+
+ // APPLE_framebuffer_multisample
+ void(GLAPIENTRY* fResolveMultisampleFramebufferAPPLE)(void);
+
+ // NV_texture_barrier
+ void(GLAPIENTRY* fTextureBarrier)(void);
+
+ // NV_primitive_restart
+ void(GLAPIENTRY* fPrimitiveRestartIndex)(GLuint);
+
+ // OVR_multiview2
+ void(GLAPIENTRY* fFramebufferTextureMultiview)(GLenum target,
+ GLenum attachment,
+ GLuint texture, GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+
+ // draw_buffers_indexed
+ void(GLAPIENTRY* fBlendEquationSeparatei)(GLuint, GLenum, GLenum);
+ void(GLAPIENTRY* fBlendFuncSeparatei)(GLuint, GLenum, GLenum, GLenum, GLenum);
+ void(GLAPIENTRY* fColorMaski)(GLuint, realGLboolean, realGLboolean,
+ realGLboolean, realGLboolean);
+ void(GLAPIENTRY* fDisablei)(GLenum, GLuint);
+ void(GLAPIENTRY* fEnablei)(GLenum, GLuint);
+
+ // provoking_vertex
+ void(GLAPIENTRY* fProvokingVertex)(GLenum);
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif /* GLCONTEXTSYMBOLS_H_ */
diff --git a/gfx/gl/GLContextTypes.h b/gfx/gl/GLContextTypes.h
new file mode 100644
index 0000000000..09ea3c21a7
--- /dev/null
+++ b/gfx/gl/GLContextTypes.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXT_TYPES_H_
+#define GLCONTEXT_TYPES_H_
+
+#include "GLTypes.h"
+#include "mozilla/DefineEnum.h"
+#include "mozilla/TypedEnumBits.h"
+
+namespace mozilla {
+namespace gl {
+
+class GLContext;
+
+enum class GLContextType { Unknown, WGL, CGL, GLX, EGL, EAGL };
+
+enum class OriginPos : uint8_t { TopLeft, BottomLeft };
+
+enum class CreateContextFlags : uint16_t {
+ NONE = 0,
+ REQUIRE_COMPAT_PROFILE = 1 << 0,
+ // Force the use of hardware backed GL, don't allow software implementations.
+ FORBID_SOFTWARE = 1 << 1,
+ /* Don't force discrete GPU to be used (if applicable) */
+ ALLOW_OFFLINE_RENDERER = 1 << 2,
+ // Ask for ES3 if possible
+ PREFER_ES3 = 1 << 3,
+
+ NO_VALIDATION = 1 << 4,
+ PREFER_ROBUSTNESS = 1 << 5,
+ HIGH_POWER = 1 << 6,
+ PROVOKING_VERTEX_DONT_CARE = 1 << 7,
+ PREFER_EXACT_VERSION = 1 << 8,
+ PREFER_MULTITHREADED = 1 << 9,
+
+ FORBID_HARDWARE = 1 << 10,
+};
+MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags)
+
+struct GLContextCreateDesc {
+ CreateContextFlags flags = CreateContextFlags::NONE;
+};
+
+struct GLContextDesc final : public GLContextCreateDesc {
+ bool isOffscreen = false;
+};
+
+// -
+
+MOZ_DEFINE_ENUM_CLASS_WITH_BASE(GLVendor, uint8_t,
+ (Intel, NVIDIA, ATI, Qualcomm, Imagination,
+ Nouveau, Vivante, VMware, ARM, Other));
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* GLCONTEXT_TYPES_H_ */
diff --git a/gfx/gl/GLContextWGL.h b/gfx/gl/GLContextWGL.h
new file mode 100644
index 0000000000..9a86031d46
--- /dev/null
+++ b/gfx/gl/GLContextWGL.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLCONTEXTWGL_H_
+#define GLCONTEXTWGL_H_
+
+#include "GLContext.h"
+#include "WGLLibrary.h"
+
+namespace mozilla {
+namespace gl {
+
+class GLContextWGL final : public GLContext {
+ public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextWGL, override)
+ // From Window: (possibly for offscreen!)
+ GLContextWGL(const GLContextDesc&, HDC aDC, HGLRC aContext,
+ HWND aWindow = nullptr);
+
+ // From PBuffer
+ GLContextWGL(const GLContextDesc&, HANDLE aPbuffer, HDC aDC, HGLRC aContext,
+ int aPixelFormat);
+
+ ~GLContextWGL();
+
+ virtual GLContextType GetContextType() const override {
+ return GLContextType::WGL;
+ }
+
+ virtual bool MakeCurrentImpl() const override;
+ virtual bool IsCurrentImpl() const override;
+ virtual bool IsDoubleBuffered() const override { return mIsDoubleBuffered; }
+ virtual bool SwapBuffers() override;
+ virtual void GetWSIInfo(nsCString* const out) const override;
+
+ Maybe<SymbolLoader> GetSymbolLoader() const override {
+ return Some(sWGLLib.GetSymbolLoader());
+ }
+
+ HGLRC Context() { return mContext; }
+
+ protected:
+ friend class GLContextProviderWGL;
+
+ HDC mDC;
+ HGLRC mContext;
+ HWND mWnd;
+ HANDLE mPBuffer;
+ int mPixelFormat;
+
+ public:
+ bool mIsDoubleBuffered = false;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLCONTEXTWGL_H_
diff --git a/gfx/gl/GLDebugUtils.cpp b/gfx/gl/GLDebugUtils.cpp
new file mode 100644
index 0000000000..463ecf2730
--- /dev/null
+++ b/gfx/gl/GLDebugUtils.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLDebugUtils.h"
+#include "GLConsts.h"
+
+namespace mozilla {
+namespace gl {
+
+const char* GLenumToStr(GLenum e) {
+ switch (e) {
+#define HANDLE_GL_ENUM(x) \
+ case LOCAL_##x: \
+ return #x
+ HANDLE_GL_ENUM(GL_TRIANGLES);
+ HANDLE_GL_ENUM(GL_TRIANGLE_STRIP);
+ HANDLE_GL_ENUM(GL_TRIANGLE_FAN);
+ HANDLE_GL_ENUM(GL_FRAMEBUFFER);
+ HANDLE_GL_ENUM(GL_RENDERBUFFER);
+ HANDLE_GL_ENUM(GL_DEPTH_ATTACHMENT);
+ HANDLE_GL_ENUM(GL_STENCIL_ATTACHMENT);
+ HANDLE_GL_ENUM(GL_DEPTH_STENCIL_ATTACHMENT);
+ HANDLE_GL_ENUM(GL_TEXTURE_2D);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
+ HANDLE_GL_ENUM(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT0);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT1);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT2);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT3);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT4);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT5);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT6);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT7);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT8);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT9);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT10);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT11);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT12);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT13);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT14);
+ HANDLE_GL_ENUM(GL_COLOR_ATTACHMENT15);
+ HANDLE_GL_ENUM(GL_UNSIGNED_BYTE);
+ HANDLE_GL_ENUM(GL_UNSIGNED_SHORT);
+ HANDLE_GL_ENUM(GL_UNSIGNED_INT);
+ HANDLE_GL_ENUM(GL_RGBA);
+ HANDLE_GL_ENUM(GL_DEPTH_COMPONENT);
+#undef HANDLE_GL_ENUM
+ }
+
+ return "(unknown)";
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLDebugUtils.h b/gfx/gl/GLDebugUtils.h
new file mode 100644
index 0000000000..d817d060dd
--- /dev/null
+++ b/gfx/gl/GLDebugUtils.h
@@ -0,0 +1,19 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLDEBUGUTILS_H_
+#define GLDEBUGUTILS_H_
+
+#include "GLTypes.h"
+
+namespace mozilla {
+namespace gl {
+
+const char* GLenumToStr(GLenum e);
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // !GLDEBUGUTILS_H_
diff --git a/gfx/gl/GLDefs.h b/gfx/gl/GLDefs.h
new file mode 100644
index 0000000000..56f8031493
--- /dev/null
+++ b/gfx/gl/GLDefs.h
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined(LOCALGL_H_)
+# define LOCALGL_H_
+
+# include "GLTypes.h"
+# include "GLConsts.h"
+
+namespace mozilla {
+namespace gl {
+class GLContext;
+bool CheckContextLost(const GLContext* gl);
+} // namespace gl
+} // namespace mozilla
+
+# define MOZ_GL_ASSERT(glContext, expr) \
+ MOZ_ASSERT((expr) || mozilla::gl::CheckContextLost(glContext))
+
+// -
+
+// clang-format off
+
+// TODO: use official constant names instead of followed ones.
+
+// IMG_texture_compression_pvrtc
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1 0x8C00
+#define LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1 0x8C01
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1 0x8C02
+#define LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 0x8C03
+
+// OES_EGL_image_external
+#define LOCAL_GL_TEXTURE_EXTERNAL 0x8D65
+#define LOCAL_GL_TEXTURE_BINDING_EXTERNAL 0x8D67
+
+// AMD_compressed_ATC_texture
+#define LOCAL_GL_ATC_RGB 0x8C92
+#define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA 0x8C93
+#define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA 0x87EE
+
+// EGL_ANDROID_image_crop
+#define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID 0x3148
+#define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID 0x3149
+#define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID 0x314A
+#define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B
+
+// EGL_ANGLE_platform_angle
+#define LOCAL_EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define LOCAL_EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define LOCAL_EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
+#define LOCAL_EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE 0x3451
+
+// EGL_ANGLE_keyed_mutex
+#define LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
+
+// EGL_ANGLE_stream_producer_d3d_texture
+#define LOCAL_EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE 0x33AB
+
+// EGL_ANGLE_platform_angle_d3d
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
+#define LOCAL_EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+
+// EGL_ANGLE_d3d_texture_client_buffer
+#define LOCAL_EGL_D3D_TEXTURE_ANGLE 0x33A3
+
+// EGL_ANGLE_flexible_surface_compatibility
+#define LOCAL_EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6
+
+// EGL_ANGLE_experimental_present_path
+#define LOCAL_EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE 0x33A4
+#define LOCAL_EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE 0x33A9
+#define LOCAL_EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE 0x33AA
+
+// EGL_ANGLE_direct3d_display
+#define LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2)
+#define LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3)
+
+// EGL_ANGLE_feature_control
+#define LOCAL_EGL_FEATURE_OVERRIDES_ENABLED_ANGLE 0x3466
+
+// WGL_NV_DX_interop
+#define LOCAL_WGL_ACCESS_READ_ONLY 0x0000
+#define LOCAL_WGL_ACCESS_READ_WRITE 0x0001
+#define LOCAL_WGL_ACCESS_WRITE_DISCARD 0x0002
+
+// Others
+#define LOCAL_EGL_PRESERVED_RESOURCES 0x3030
+#define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
+#define LOCAL_GL_CONTEXT_FLAGS_ARB 0x2094
+#define LOCAL_GL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define LOCAL_GL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+
+// EGL_ANGLE_create_context_backwards_compatible
+#define LOCAL_EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
+
+// EGL_ANGLE_image_d3d11_texture
+#define LOCAL_EGL_D3D11_TEXTURE_ANGLE 0x3484
+
+// clang-format on
+
+#endif
diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp
new file mode 100644
index 0000000000..e27081dc95
--- /dev/null
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -0,0 +1,1079 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLLibraryEGL.h"
+
+#include "gfxConfig.h"
+#include "gfxCrashReporterUtils.h"
+#include "gfxEnv.h"
+#include "gfxUtils.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/Tokenizer.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/StaticPrefs_gfx.h"
+#include "mozilla/StaticPrefs_webgl.h"
+#include "mozilla/Unused.h"
+#include "nsDirectoryServiceDefs.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsPrintfCString.h"
+#ifdef XP_WIN
+# include "mozilla/gfx/DeviceManagerDx.h"
+# include "nsWindowsHelpers.h"
+# include "prerror.h"
+
+# include <d3d11.h>
+#endif
+#include "OGLShaderProgram.h"
+#include "prenv.h"
+#include "prsystem.h"
+#include "GLContext.h"
+#include "GLContextProvider.h"
+#include "GLLibraryLoader.h"
+#include "GLReadTexImageHelper.h"
+#include "ScopedGLHelpers.h"
+#ifdef MOZ_WIDGET_GTK
+# include "mozilla/WidgetUtilsGtk.h"
+# include "mozilla/widget/DMABufLibWrapper.h"
+# ifdef MOZ_WAYLAND
+# include "mozilla/widget/nsWaylandDisplay.h"
+# endif // MOZ_WIDGET_GTK
+# include <gdk/gdk.h>
+#endif // MOZ_WAYLAND
+
+#include <mutex> // for call_once
+
+namespace mozilla {
+namespace gl {
+
+StaticMutex GLLibraryEGL::sMutex;
+StaticRefPtr<GLLibraryEGL> GLLibraryEGL::sInstance;
+
+// should match the order of EGLExtensions, and be null-terminated.
+static const char* sEGLLibraryExtensionNames[] = {
+ "EGL_ANDROID_get_native_client_buffer",
+ "EGL_ANGLE_device_creation",
+ "EGL_ANGLE_device_creation_d3d11",
+ "EGL_ANGLE_platform_angle",
+ "EGL_ANGLE_platform_angle_d3d",
+ "EGL_EXT_device_enumeration",
+ "EGL_EXT_device_query",
+ "EGL_EXT_platform_device",
+ "EGL_MESA_platform_surfaceless"};
+
+// should match the order of EGLExtensions, and be null-terminated.
+static const char* sEGLExtensionNames[] = {
+ "EGL_KHR_image_base",
+ "EGL_KHR_image_pixmap",
+ "EGL_KHR_gl_texture_2D_image",
+ "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
+ "EGL_EXT_create_context_robustness",
+ "EGL_KHR_image",
+ "EGL_KHR_fence_sync",
+ "EGL_KHR_wait_sync",
+ "EGL_ANDROID_native_fence_sync",
+ "EGL_ANDROID_image_crop",
+ "EGL_ANGLE_d3d_share_handle_client_buffer",
+ "EGL_KHR_create_context",
+ "EGL_KHR_stream",
+ "EGL_KHR_stream_consumer_gltexture",
+ "EGL_NV_stream_consumer_gltexture_yuv",
+ "EGL_ANGLE_stream_producer_d3d_texture",
+ "EGL_KHR_surfaceless_context",
+ "EGL_KHR_create_context_no_error",
+ "EGL_MOZ_create_context_provoking_vertex_dont_care",
+ "EGL_EXT_swap_buffers_with_damage",
+ "EGL_KHR_swap_buffers_with_damage",
+ "EGL_EXT_buffer_age",
+ "EGL_KHR_partial_update",
+ "EGL_NV_robustness_video_memory_purge",
+ "EGL_EXT_image_dma_buf_import",
+ "EGL_EXT_image_dma_buf_import_modifiers",
+ "EGL_MESA_image_dma_buf_export",
+ "EGL_KHR_no_config_context",
+};
+
+PRLibrary* LoadApitraceLibrary() {
+ const char* path = nullptr;
+
+#ifdef ANDROID
+ // We only need to explicitly dlopen egltrace
+ // on android as we can use LD_PRELOAD or other tricks
+ // on other platforms. We look for it in /data/local
+ // as that's writeable by all users.
+ path = "/data/local/tmp/egltrace.so";
+#endif
+ if (!path) return nullptr;
+
+ // Initialization of gfx prefs here is only needed during the unit tests...
+ if (!StaticPrefs::gfx_apitrace_enabled_AtStartup()) {
+ return nullptr;
+ }
+
+ static PRLibrary* sApitraceLibrary = nullptr;
+ if (sApitraceLibrary) return sApitraceLibrary;
+
+ nsAutoCString logFile;
+ Preferences::GetCString("gfx.apitrace.logfile", logFile);
+ if (logFile.IsEmpty()) {
+ logFile = "firefox.trace";
+ }
+
+ // The firefox process can't write to /data/local, but it can write
+ // to $GRE_HOME/
+ nsAutoCString logPath;
+ logPath.AppendPrintf("%s/%s", getenv("GRE_HOME"), logFile.get());
+
+#ifndef XP_WIN // Windows is missing setenv and forbids PR_LoadLibrary.
+ // apitrace uses the TRACE_FILE environment variable to determine where
+ // to log trace output to
+ printf_stderr("Logging GL tracing output to %s", logPath.get());
+ setenv("TRACE_FILE", logPath.get(), false);
+
+ printf_stderr("Attempting load of %s\n", path);
+ sApitraceLibrary = PR_LoadLibrary(path);
+#endif
+
+ return sApitraceLibrary;
+}
+
+#ifdef XP_WIN
+// see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here.
+static PRLibrary* LoadLibraryForEGLOnWindows(const nsAString& filename) {
+ nsAutoString path(gfx::gfxVars::GREDirectory());
+ path.Append(PR_GetDirectorySeparator());
+ path.Append(filename);
+
+ PRLibSpec lspec;
+ lspec.type = PR_LibSpec_PathnameU;
+ lspec.value.pathname_u = path.get();
+ PRLibrary* lib = PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL);
+ if (!lib) {
+ gfxCriticalNote << "Failed to load " << path.get() << " " << PR_GetError()
+ << " " << PR_GetOSError();
+ }
+ return lib;
+}
+
+#endif // XP_WIN
+
+static std::shared_ptr<EglDisplay> GetAndInitDisplay(
+ GLLibraryEGL& egl, void* displayType,
+ const StaticMutexAutoLock& aProofOfLock) {
+ const auto display = egl.fGetDisplay(displayType);
+ if (!display) return nullptr;
+ return EglDisplay::Create(egl, display, false, aProofOfLock);
+}
+
+#ifdef MOZ_WIDGET_GTK
+static std::shared_ptr<EglDisplay> GetAndInitDeviceDisplay(
+ GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) {
+ nsAutoCString drmRenderDevice(gfx::gfxVars::DrmRenderDevice());
+ if (drmRenderDevice.IsEmpty() ||
+ !egl.IsExtensionSupported(EGLLibExtension::EXT_platform_device) ||
+ !egl.IsExtensionSupported(EGLLibExtension::EXT_device_enumeration)) {
+ return nullptr;
+ }
+
+ EGLint maxDevices;
+ if (!egl.fQueryDevicesEXT(0, nullptr, &maxDevices)) {
+ return nullptr;
+ }
+
+ std::vector<EGLDeviceEXT> devices(maxDevices);
+ EGLint numDevices;
+ if (!egl.fQueryDevicesEXT(devices.size(), devices.data(), &numDevices)) {
+ return nullptr;
+ }
+ devices.resize(numDevices);
+
+ EGLDisplay display = EGL_NO_DISPLAY;
+ for (const auto& device : devices) {
+ const char* renderNodeString =
+ egl.fQueryDeviceStringEXT(device, LOCAL_EGL_DRM_RENDER_NODE_FILE_EXT);
+ if (renderNodeString &&
+ strcmp(renderNodeString, drmRenderDevice.get()) == 0) {
+ const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE};
+ display = egl.fGetPlatformDisplay(LOCAL_EGL_PLATFORM_DEVICE_EXT, device,
+ attrib_list);
+ break;
+ }
+ }
+ if (!display) {
+ return nullptr;
+ }
+
+ return EglDisplay::Create(egl, display, true, aProofOfLock);
+}
+
+static std::shared_ptr<EglDisplay> GetAndInitSoftwareDisplay(
+ GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) {
+ if (!egl.IsExtensionSupported(EGLLibExtension::EXT_platform_device) ||
+ !egl.IsExtensionSupported(EGLLibExtension::EXT_device_enumeration)) {
+ return nullptr;
+ }
+
+ EGLint maxDevices;
+ if (!egl.fQueryDevicesEXT(0, nullptr, &maxDevices)) {
+ return nullptr;
+ }
+
+ std::vector<EGLDeviceEXT> devices(maxDevices);
+ EGLint numDevices;
+ if (!egl.fQueryDevicesEXT(devices.size(), devices.data(), &numDevices)) {
+ return nullptr;
+ }
+ devices.resize(numDevices);
+
+ EGLDisplay display = EGL_NO_DISPLAY;
+ for (const auto& device : devices) {
+ const char* renderNodeString =
+ egl.fQueryDeviceStringEXT(device, LOCAL_EGL_DRM_RENDER_NODE_FILE_EXT);
+ // We are looking for a device with no file
+ if (!renderNodeString || *renderNodeString == 0) {
+ const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE};
+ display = egl.fGetPlatformDisplay(LOCAL_EGL_PLATFORM_DEVICE_EXT, device,
+ attrib_list);
+ break;
+ }
+ }
+ if (!display) {
+ return nullptr;
+ }
+
+ return EglDisplay::Create(egl, display, true, aProofOfLock);
+}
+
+static std::shared_ptr<EglDisplay> GetAndInitSurfacelessDisplay(
+ GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) {
+ if (!egl.IsExtensionSupported(EGLLibExtension::MESA_platform_surfaceless)) {
+ return nullptr;
+ }
+
+ const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE};
+ const EGLDisplay display = egl.fGetPlatformDisplay(
+ LOCAL_EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, attrib_list);
+ if (display == EGL_NO_DISPLAY) {
+ return nullptr;
+ }
+ return EglDisplay::Create(egl, display, true, aProofOfLock);
+}
+#endif
+
+static auto EglDebugLayersEnabled() {
+ EGLAttrib ret = LOCAL_EGL_FALSE;
+ if (StaticPrefs::gfx_direct3d11_enable_debug_layer_AtStartup()) {
+ ret = LOCAL_EGL_TRUE;
+ }
+ return ret;
+}
+
+static std::shared_ptr<EglDisplay> GetAndInitWARPDisplay(
+ GLLibraryEGL& egl, void* displayType,
+ const StaticMutexAutoLock& aProofOfLock) {
+ const EGLAttrib attrib_list[] = {
+ LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+ LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
+ LOCAL_EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE,
+ EglDebugLayersEnabled(),
+ // Requires:
+ LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+ LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, LOCAL_EGL_NONE};
+ const EGLDisplay display = egl.fGetPlatformDisplay(
+ LOCAL_EGL_PLATFORM_ANGLE_ANGLE, displayType, attrib_list);
+
+ if (display == EGL_NO_DISPLAY) {
+ const EGLint err = egl.fGetError();
+ if (err != LOCAL_EGL_SUCCESS) {
+ gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
+ MOZ_CRASH("GFX: Unexpected GL error.");
+ }
+ return nullptr;
+ }
+
+ return EglDisplay::Create(egl, display, true, aProofOfLock);
+}
+
+std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
+ ID3D11Device* const d3d11Device) {
+ StaticMutexAutoLock lock(sMutex);
+ EGLDeviceEXT eglDevice =
+ fCreateDeviceANGLE(LOCAL_EGL_D3D11_DEVICE_ANGLE, d3d11Device, nullptr);
+ if (!eglDevice) {
+ gfxCriticalNote << "Failed to get EGLDeviceEXT of D3D11Device";
+ return nullptr;
+ }
+ const char* features[] = {"allowES3OnFL10_0", nullptr};
+ // Create an EGLDisplay using the EGLDevice
+ const EGLAttrib attrib_list[] = {LOCAL_EGL_FEATURE_OVERRIDES_ENABLED_ANGLE,
+ reinterpret_cast<EGLAttrib>(features),
+ LOCAL_EGL_NONE};
+ const auto display = fGetPlatformDisplay(LOCAL_EGL_PLATFORM_DEVICE_EXT,
+ eglDevice, attrib_list);
+ if (!display) {
+ gfxCriticalNote << "Failed to get EGLDisplay of D3D11Device";
+ return nullptr;
+ }
+
+ if (!display) {
+ const EGLint err = fGetError();
+ if (err != LOCAL_EGL_SUCCESS) {
+ gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
+ MOZ_CRASH("GFX: Unexpected GL error.");
+ }
+ return nullptr;
+ }
+
+ const auto ret = EglDisplay::Create(*this, display, false, lock);
+
+ if (!ret) {
+ const EGLint err = fGetError();
+ if (err != LOCAL_EGL_SUCCESS) {
+ gfxCriticalError()
+ << "Failed to initialize EGLDisplay for WebRender error: "
+ << gfx::hexa(err);
+ }
+ return nullptr;
+ }
+ return ret;
+}
+
+static bool IsAccelAngleSupported(nsACString* const out_failureId) {
+ if (!gfx::gfxVars::AllowWebglAccelAngle()) {
+ if (out_failureId->IsEmpty()) {
+ *out_failureId = "FEATURE_FAILURE_ACCL_ANGLE_NOT_OK"_ns;
+ }
+ return false;
+ }
+ return true;
+}
+
+class AngleErrorReporting {
+ public:
+ AngleErrorReporting() : mFailureId(nullptr) {
+ // No static constructor
+ }
+
+ void SetFailureId(nsACString* const aFailureId) { mFailureId = aFailureId; }
+
+ void logError(const char* errorMessage) {
+ if (!mFailureId) {
+ return;
+ }
+
+ nsCString str(errorMessage);
+ Tokenizer tokenizer(str);
+
+ // Parse "ANGLE Display::initialize error " << error.getID() << ": "
+ // << error.getMessage()
+ nsCString currWord;
+ Tokenizer::Token intToken;
+ if (tokenizer.CheckWord("ANGLE") && tokenizer.CheckWhite() &&
+ tokenizer.CheckWord("Display") && tokenizer.CheckChar(':') &&
+ tokenizer.CheckChar(':') && tokenizer.CheckWord("initialize") &&
+ tokenizer.CheckWhite() && tokenizer.CheckWord("error") &&
+ tokenizer.CheckWhite() &&
+ tokenizer.Check(Tokenizer::TOKEN_INTEGER, intToken)) {
+ *mFailureId = "FAILURE_ID_ANGLE_ID_";
+ mFailureId->AppendPrintf("%" PRIu64, intToken.AsInteger());
+ } else {
+ *mFailureId = "FAILURE_ID_ANGLE_UNKNOWN";
+ }
+ }
+
+ private:
+ nsACString* mFailureId;
+};
+
+AngleErrorReporting gAngleErrorReporter;
+
+static std::shared_ptr<EglDisplay> GetAndInitDisplayForAccelANGLE(
+ GLLibraryEGL& egl, nsACString* const out_failureId,
+ const StaticMutexAutoLock& aProofOfLock) {
+ gfx::FeatureState& d3d11ANGLE =
+ gfx::gfxConfig::GetFeature(gfx::Feature::D3D11_HW_ANGLE);
+
+ if (!StaticPrefs::webgl_angle_try_d3d11()) {
+ d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref",
+ "FAILURE_ID_ANGLE_PREF"_ns);
+ }
+ if (StaticPrefs::webgl_angle_force_d3d11()) {
+ d3d11ANGLE.UserForceEnable(
+ "User force-enabled D3D11 ANGLE on disabled hardware");
+ }
+ gAngleErrorReporter.SetFailureId(out_failureId);
+
+ auto guardShutdown = mozilla::MakeScopeExit([&] {
+ gAngleErrorReporter.SetFailureId(nullptr);
+ // NOTE: Ideally we should be calling ANGLEPlatformShutdown after the
+ // ANGLE display is destroyed. However gAngleErrorReporter
+ // will live longer than the ANGLE display so we're fine.
+ });
+
+ if (gfx::gfxConfig::IsForcedOnByUser(gfx::Feature::D3D11_HW_ANGLE)) {
+ return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE,
+ aProofOfLock);
+ }
+
+ std::shared_ptr<EglDisplay> ret;
+ if (d3d11ANGLE.IsEnabled()) {
+ ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE,
+ aProofOfLock);
+ }
+
+ if (!ret) {
+ ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY, aProofOfLock);
+ }
+
+ if (!ret && out_failureId->IsEmpty()) {
+ *out_failureId = "FEATURE_FAILURE_ACCL_ANGLE_NO_DISP"_ns;
+ }
+
+ return ret;
+}
+
+// -
+
+#if defined(XP_UNIX)
+# define GLES2_LIB "libGLESv2.so"
+# define GLES2_LIB2 "libGLESv2.so.2"
+# define GL_LIB "libGL.so"
+# define GL_LIB2 "libGL.so.1"
+#elif defined(XP_WIN)
+# define GLES2_LIB "libGLESv2.dll"
+#else
+# error "Platform not recognized"
+#endif
+
+Maybe<SymbolLoader> GLLibraryEGL::GetSymbolLoader() const {
+ auto ret = SymbolLoader(mSymbols.fGetProcAddress);
+ ret.mLib = mGLLibrary;
+ return Some(ret);
+}
+
+// -
+
+/* static */
+RefPtr<GLLibraryEGL> GLLibraryEGL::Get(nsACString* const out_failureId) {
+ StaticMutexAutoLock lock(sMutex);
+ if (!sInstance) {
+ sInstance = new GLLibraryEGL;
+ if (NS_WARN_IF(!sInstance->Init(out_failureId))) {
+ sInstance = nullptr;
+ }
+ }
+ return sInstance;
+}
+
+/* static */ void GLLibraryEGL::Shutdown() {
+ StaticMutexAutoLock lock(sMutex);
+ sInstance = nullptr;
+}
+
+bool GLLibraryEGL::Init(nsACString* const out_failureId) {
+ MOZ_RELEASE_ASSERT(!mSymbols.fTerminate);
+
+ mozilla::ScopedGfxFeatureReporter reporter("EGL");
+
+#ifdef XP_WIN
+ if (!mEGLLibrary) {
+ // On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul
+ // and we should look for them there. We have to load the libs in this
+ // order, because libEGL.dll depends on libGLESv2.dll which depends on the
+ // DXSDK libraries. This matters especially for WebRT apps which are in a
+ // different directory. See bug 760323 and bug 749459
+
+ // Also note that we intentionally leak the libs we load.
+
+ do {
+ // Windows 8.1+ has d3dcompiler_47.dll in the system directory.
+ if (LoadLibrarySystem32(L"d3dcompiler_47.dll")) break;
+
+ MOZ_ASSERT(false, "d3dcompiler DLL loading failed.");
+ } while (false);
+
+ mGLLibrary = LoadLibraryForEGLOnWindows(u"libGLESv2.dll"_ns);
+
+ mEGLLibrary = LoadLibraryForEGLOnWindows(u"libEGL.dll"_ns);
+ }
+
+#else // !Windows
+
+ // On non-Windows (Android) we use system copies of libEGL. We look for
+ // the APITrace lib, libEGL.so, and libEGL.so.1 in that order.
+
+# if defined(ANDROID)
+ if (!mEGLLibrary) mEGLLibrary = LoadApitraceLibrary();
+# endif
+
+ if (!mEGLLibrary) {
+ mEGLLibrary = PR_LoadLibrary("libEGL.so");
+ }
+# if defined(XP_UNIX)
+ if (!mEGLLibrary) {
+ mEGLLibrary = PR_LoadLibrary("libEGL.so.1");
+ }
+# endif
+
+# ifdef APITRACE_LIB
+ if (!mGLLibrary) {
+ mGLLibrary = PR_LoadLibrary(APITRACE_LIB);
+ }
+# endif
+
+# ifdef GL_LIB
+ if (!mGLLibrary) {
+ mGLLibrary = PR_LoadLibrary(GL_LIB);
+ }
+# endif
+
+# ifdef GL_LIB2
+ if (!mGLLibrary) {
+ mGLLibrary = PR_LoadLibrary(GL_LIB2);
+ }
+# endif
+
+ if (!mGLLibrary) {
+ mGLLibrary = PR_LoadLibrary(GLES2_LIB);
+ }
+
+# ifdef GLES2_LIB2
+ if (!mGLLibrary) {
+ mGLLibrary = PR_LoadLibrary(GLES2_LIB2);
+ }
+# endif
+
+#endif // !Windows
+
+ if (!mEGLLibrary || !mGLLibrary) {
+ NS_WARNING("Couldn't load EGL LIB.");
+ *out_failureId = "FEATURE_FAILURE_EGL_LOAD_3"_ns;
+ return false;
+ }
+
+#define SYMBOL(X) \
+ { \
+ (PRFuncPtr*)&mSymbols.f##X, { \
+ { "egl" #X } \
+ } \
+ }
+#define END_OF_SYMBOLS \
+ { \
+ nullptr, {} \
+ }
+
+ SymLoadStruct earlySymbols[] = {SYMBOL(GetDisplay),
+ SYMBOL(Terminate),
+ SYMBOL(GetCurrentSurface),
+ SYMBOL(GetCurrentContext),
+ SYMBOL(MakeCurrent),
+ SYMBOL(DestroyContext),
+ SYMBOL(CreateContext),
+ SYMBOL(DestroySurface),
+ SYMBOL(CreateWindowSurface),
+ SYMBOL(CreatePbufferSurface),
+ SYMBOL(CreatePbufferFromClientBuffer),
+ SYMBOL(CreatePixmapSurface),
+ SYMBOL(BindAPI),
+ SYMBOL(Initialize),
+ SYMBOL(ChooseConfig),
+ SYMBOL(GetError),
+ SYMBOL(GetConfigs),
+ SYMBOL(GetConfigAttrib),
+ SYMBOL(WaitNative),
+ SYMBOL(GetProcAddress),
+ SYMBOL(SwapBuffers),
+ SYMBOL(CopyBuffers),
+ SYMBOL(QueryString),
+ SYMBOL(QueryContext),
+ SYMBOL(BindTexImage),
+ SYMBOL(ReleaseTexImage),
+ SYMBOL(SwapInterval),
+ SYMBOL(QuerySurface),
+ END_OF_SYMBOLS};
+
+ {
+ const SymbolLoader libLoader(*mEGLLibrary);
+ if (!libLoader.LoadSymbols(earlySymbols)) {
+ NS_WARNING(
+ "Couldn't find required entry points in EGL library (early init)");
+ *out_failureId = "FEATURE_FAILURE_EGL_SYM"_ns;
+ return false;
+ }
+ }
+
+ {
+ const char internalFuncName[] =
+ "_Z35eglQueryStringImplementationANDROIDPvi";
+ const auto& internalFunc =
+ PR_FindFunctionSymbol(mEGLLibrary, internalFuncName);
+ if (internalFunc) {
+ *(PRFuncPtr*)&mSymbols.fQueryString = internalFunc;
+ }
+ }
+
+ // -
+
+ InitLibExtensions();
+
+ const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
+
+ const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
+ const bool shouldWarn = gfxEnv::MOZ_GL_SPEW();
+ if (pfnLoader.LoadSymbols(symbols, shouldWarn)) return true;
+
+ ClearSymbols(symbols);
+ return false;
+ };
+
+ // Check the ANGLE support the system has
+ mIsANGLE = IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle);
+
+ // Client exts are ready. (But not display exts!)
+
+ if (mIsANGLE) {
+ MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
+ const SymLoadStruct angleSymbols[] = {SYMBOL(GetPlatformDisplay),
+ END_OF_SYMBOLS};
+ if (!fnLoadSymbols(angleSymbols)) {
+ gfxCriticalError() << "Failed to load ANGLE symbols!";
+ return false;
+ }
+ MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
+ const SymLoadStruct createDeviceSymbols[] = {
+ SYMBOL(CreateDeviceANGLE), SYMBOL(ReleaseDeviceANGLE), END_OF_SYMBOLS};
+ if (!fnLoadSymbols(createDeviceSymbols)) {
+ NS_ERROR(
+ "EGL supports ANGLE_device_creation without exposing its functions!");
+ MarkExtensionUnsupported(EGLLibExtension::ANGLE_device_creation);
+ }
+ }
+
+ // ANDROID_get_native_client_buffer isn't necessarily enumerated in lib exts,
+ // but it is one.
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(GetNativeClientBufferANDROID),
+ END_OF_SYMBOLS};
+ if (fnLoadSymbols(symbols)) {
+ mAvailableExtensions[UnderlyingValue(
+ EGLLibExtension::ANDROID_get_native_client_buffer)] = true;
+ }
+ }
+
+ // -
+ // Load possible display ext symbols.
+
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(QuerySurfacePointerANGLE),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ SYMBOL(CreateSyncKHR), SYMBOL(DestroySyncKHR),
+ SYMBOL(ClientWaitSyncKHR), SYMBOL(GetSyncAttribKHR), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(CreateImageKHR),
+ SYMBOL(DestroyImageKHR), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(WaitSyncKHR), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(DupNativeFenceFDANDROID),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(CreateStreamKHR),
+ SYMBOL(DestroyStreamKHR),
+ SYMBOL(QueryStreamKHR), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(StreamConsumerGLTextureExternalKHR),
+ SYMBOL(StreamConsumerAcquireKHR),
+ SYMBOL(StreamConsumerReleaseKHR),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ SYMBOL(QueryDisplayAttribEXT), SYMBOL(QueryDeviceAttribEXT),
+ SYMBOL(QueryDeviceStringEXT), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ SYMBOL(StreamConsumerGLTextureExternalAttribsNV), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ SYMBOL(CreateStreamProducerD3DTextureANGLE),
+ SYMBOL(StreamPostD3DTextureANGLE), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
+ {{"eglSwapBuffersWithDamageEXT"}}},
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
+ {{"eglSwapBuffersWithDamageKHR"}}},
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {
+ {(PRFuncPtr*)&mSymbols.fSetDamageRegion, {{"eglSetDamageRegionKHR"}}},
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(GetPlatformDisplay),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(ExportDMABUFImageQueryMESA),
+ SYMBOL(ExportDMABUFImageMESA),
+ END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+ {
+ const SymLoadStruct symbols[] = {SYMBOL(QueryDevicesEXT), END_OF_SYMBOLS};
+ (void)fnLoadSymbols(symbols);
+ }
+
+ return true;
+}
+
+// -
+
+template <size_t N>
+static void MarkExtensions(const char* rawExtString, bool shouldDumpExts,
+ const char* extType, const char* const (&names)[N],
+ std::bitset<N>* const out) {
+ MOZ_ASSERT(rawExtString);
+
+ const nsDependentCString extString(rawExtString);
+
+ std::vector<nsCString> extList;
+ SplitByChar(extString, ' ', &extList);
+
+ if (shouldDumpExts) {
+ printf_stderr("%u EGL %s extensions: (*: recognized)\n",
+ (uint32_t)extList.size(), extType);
+ }
+
+ MarkBitfieldByStrings(extList, shouldDumpExts, names, out);
+}
+
+// -
+
+// static
+std::shared_ptr<EglDisplay> EglDisplay::Create(
+ GLLibraryEGL& lib, const EGLDisplay display, const bool isWarp,
+ const StaticMutexAutoLock& aProofOfLock) {
+ // Retrieve the EglDisplay if it already exists
+ {
+ const auto itr = lib.mActiveDisplays.find(display);
+ if (itr != lib.mActiveDisplays.end()) {
+ const auto ret = itr->second.lock();
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+
+ if (!lib.fInitialize(display, nullptr, nullptr)) {
+ return nullptr;
+ }
+
+ static std::once_flag sMesaLeakFlag;
+ std::call_once(sMesaLeakFlag, MesaMemoryLeakWorkaround);
+
+ const auto ret =
+ std::make_shared<EglDisplay>(PrivateUseOnly{}, lib, display, isWarp);
+ lib.mActiveDisplays.insert({display, ret});
+ return ret;
+}
+
+EglDisplay::EglDisplay(const PrivateUseOnly&, GLLibraryEGL& lib,
+ const EGLDisplay disp, const bool isWarp)
+ : mLib(&lib), mDisplay(disp), mIsWARP(isWarp) {
+ const bool shouldDumpExts = GLContext::ShouldDumpExts();
+
+ auto rawExtString =
+ (const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_EXTENSIONS);
+ if (!rawExtString) {
+ NS_WARNING("Failed to query EGL display extensions!.");
+ rawExtString = "";
+ }
+ MarkExtensions(rawExtString, shouldDumpExts, "display", sEGLExtensionNames,
+ &mAvailableExtensions);
+
+ // -
+
+ if (!HasKHRImageBase()) {
+ MarkExtensionUnsupported(EGLExtension::KHR_image_pixmap);
+ }
+
+ if (IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
+ const auto vendor =
+ (const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_VENDOR);
+
+ // Bug 1464610: Mali T720 (Amazon Fire 8 HD) claims to support this
+ // extension, but if you actually eglMakeCurrent() with EGL_NO_SURFACE, it
+ // fails to render anything when a real surface is provided later on. We
+ // only have the EGL vendor available here, so just avoid using this
+ // extension on all Mali devices.
+ if (vendor && (strcmp(vendor, "ARM") == 0)) {
+ MarkExtensionUnsupported(EGLExtension::KHR_surfaceless_context);
+ }
+ }
+
+ // ANDROID_native_fence_sync isn't necessarily enumerated in display ext,
+ // but it is one.
+ if (mLib->mSymbols.fDupNativeFenceFDANDROID) {
+ mAvailableExtensions[UnderlyingValue(
+ EGLExtension::ANDROID_native_fence_sync)] = true;
+ }
+}
+
+EglDisplay::~EglDisplay() {
+ StaticMutexAutoLock lock(GLLibraryEGL::sMutex);
+ fTerminate();
+ mLib->mActiveDisplays.erase(mDisplay);
+}
+
+// -
+
+std::shared_ptr<EglDisplay> GLLibraryEGL::DefaultDisplay(
+ nsACString* const out_failureId) {
+ StaticMutexAutoLock lock(sMutex);
+ auto ret = mDefaultDisplay.lock();
+ if (ret) return ret;
+
+ ret = CreateDisplayLocked(false, out_failureId, lock);
+ mDefaultDisplay = ret;
+ return ret;
+}
+
+std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
+ const bool forceAccel, nsACString* const out_failureId) {
+ StaticMutexAutoLock lock(sMutex);
+ return CreateDisplayLocked(forceAccel, out_failureId, lock);
+}
+
+std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplayLocked(
+ const bool forceAccel, nsACString* const out_failureId,
+ const StaticMutexAutoLock& aProofOfLock) {
+ std::shared_ptr<EglDisplay> ret;
+
+ if (IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d)) {
+ nsCString accelAngleFailureId;
+ bool accelAngleSupport = IsAccelAngleSupported(&accelAngleFailureId);
+ bool shouldTryAccel = forceAccel || accelAngleSupport;
+ bool shouldTryWARP = !forceAccel; // Only if ANGLE not supported or fails
+
+ // If WARP preferred, will override ANGLE support
+ if (StaticPrefs::webgl_angle_force_warp()) {
+ shouldTryWARP = true;
+ shouldTryAccel = false;
+ if (accelAngleFailureId.IsEmpty()) {
+ accelAngleFailureId = "FEATURE_FAILURE_FORCE_WARP"_ns;
+ }
+ }
+
+ // Hardware accelerated ANGLE path (supported or force accel)
+ if (shouldTryAccel) {
+ ret = GetAndInitDisplayForAccelANGLE(*this, out_failureId, aProofOfLock);
+ }
+
+ // Report the acceleration status to telemetry
+ if (!ret) {
+ if (accelAngleFailureId.IsEmpty()) {
+ Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
+ "FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN"_ns);
+ } else {
+ Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
+ accelAngleFailureId);
+ }
+ } else {
+ Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
+ "SUCCESS"_ns);
+ }
+
+ // Fallback to a WARP display if ANGLE fails, or if WARP is forced
+ if (!ret && shouldTryWARP) {
+ ret = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY, aProofOfLock);
+ if (!ret) {
+ if (out_failureId->IsEmpty()) {
+ *out_failureId = "FEATURE_FAILURE_WARP_FALLBACK"_ns;
+ }
+ NS_ERROR("Fallback WARP context failed to initialize.");
+ return nullptr;
+ }
+ }
+ } else {
+ void* nativeDisplay = EGL_DEFAULT_DISPLAY;
+#ifdef MOZ_WIDGET_GTK
+ if (!ret && !gfx::gfxVars::WebglUseHardware()) {
+ // Initialize a swrast egl device such as llvmpipe
+ ret = GetAndInitSoftwareDisplay(*this, aProofOfLock);
+ }
+ // Initialize the display the normal way
+ if (!ret && !gdk_display_get_default()) {
+ ret = GetAndInitDeviceDisplay(*this, aProofOfLock);
+ if (!ret) {
+ ret = GetAndInitSurfacelessDisplay(*this, aProofOfLock);
+ }
+ }
+# ifdef MOZ_WAYLAND
+ else if (!ret && widget::GdkIsWaylandDisplay()) {
+ // Wayland does not support EGL_DEFAULT_DISPLAY
+ nativeDisplay = widget::WaylandDisplayGetWLDisplay();
+ if (!nativeDisplay) {
+ NS_WARNING("Failed to get wl_display.");
+ return nullptr;
+ }
+ }
+# endif
+#endif
+ if (!ret) {
+ ret = GetAndInitDisplay(*this, nativeDisplay, aProofOfLock);
+ }
+ }
+
+ if (!ret) {
+ if (out_failureId->IsEmpty()) {
+ *out_failureId = "FEATURE_FAILURE_NO_DISPLAY"_ns;
+ }
+ NS_WARNING("Failed to initialize a display.");
+ return nullptr;
+ }
+
+ return ret;
+}
+
+void GLLibraryEGL::InitLibExtensions() {
+ const bool shouldDumpExts = GLContext::ShouldDumpExts();
+
+ const char* rawExtString = nullptr;
+
+#ifndef ANDROID
+ // Bug 1209612: Crashes on a number of android drivers.
+ // Ideally we would only blocklist this there, but for now we don't need the
+ // client extension list on ANDROID (we mostly need it on ANGLE), and we'd
+ // rather not crash.
+ rawExtString = (const char*)fQueryString(nullptr, LOCAL_EGL_EXTENSIONS);
+#endif
+
+ if (!rawExtString) {
+ if (shouldDumpExts) {
+ printf_stderr("No EGL lib extensions.\n");
+ }
+ return;
+ }
+
+ MarkExtensions(rawExtString, shouldDumpExts, "lib", sEGLLibraryExtensionNames,
+ &mAvailableExtensions);
+}
+
+void EglDisplay::DumpEGLConfig(EGLConfig cfg) const {
+#define ATTR(_x) \
+ do { \
+ int attrval = 0; \
+ mLib->fGetConfigAttrib(mDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
+ const auto err = mLib->fGetError(); \
+ if (err != 0x3000) { \
+ printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
+ } else { \
+ printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
+ } \
+ } while (0)
+
+ printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
+
+ ATTR(BUFFER_SIZE);
+ ATTR(ALPHA_SIZE);
+ ATTR(BLUE_SIZE);
+ ATTR(GREEN_SIZE);
+ ATTR(RED_SIZE);
+ ATTR(DEPTH_SIZE);
+ ATTR(STENCIL_SIZE);
+ ATTR(CONFIG_CAVEAT);
+ ATTR(CONFIG_ID);
+ ATTR(LEVEL);
+ ATTR(MAX_PBUFFER_HEIGHT);
+ ATTR(MAX_PBUFFER_PIXELS);
+ ATTR(MAX_PBUFFER_WIDTH);
+ ATTR(NATIVE_RENDERABLE);
+ ATTR(NATIVE_VISUAL_ID);
+ ATTR(NATIVE_VISUAL_TYPE);
+ ATTR(PRESERVED_RESOURCES);
+ ATTR(SAMPLES);
+ ATTR(SAMPLE_BUFFERS);
+ ATTR(SURFACE_TYPE);
+ ATTR(TRANSPARENT_TYPE);
+ ATTR(TRANSPARENT_RED_VALUE);
+ ATTR(TRANSPARENT_GREEN_VALUE);
+ ATTR(TRANSPARENT_BLUE_VALUE);
+ ATTR(BIND_TO_TEXTURE_RGB);
+ ATTR(BIND_TO_TEXTURE_RGBA);
+ ATTR(MIN_SWAP_INTERVAL);
+ ATTR(MAX_SWAP_INTERVAL);
+ ATTR(LUMINANCE_SIZE);
+ ATTR(ALPHA_MASK_SIZE);
+ ATTR(COLOR_BUFFER_TYPE);
+ ATTR(RENDERABLE_TYPE);
+ ATTR(CONFORMANT);
+
+#undef ATTR
+}
+
+void EglDisplay::DumpEGLConfigs() const {
+ int nc = 0;
+ mLib->fGetConfigs(mDisplay, nullptr, 0, &nc);
+ std::vector<EGLConfig> ec(nc);
+ mLib->fGetConfigs(mDisplay, ec.data(), ec.size(), &nc);
+
+ for (int i = 0; i < nc; ++i) {
+ printf_stderr("========= EGL Config %d ========\n", i);
+ DumpEGLConfig(ec[i]);
+ }
+}
+
+static bool ShouldTrace() {
+ static bool ret = gfxEnv::MOZ_GL_DEBUG_VERBOSE();
+ return ret;
+}
+
+void BeforeEGLCall(const char* glFunction) {
+ if (ShouldTrace()) {
+ printf_stderr("[egl] > %s\n", glFunction);
+ }
+}
+
+void AfterEGLCall(const char* glFunction) {
+ if (ShouldTrace()) {
+ printf_stderr("[egl] < %s\n", glFunction);
+ }
+}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h
new file mode 100644
index 0000000000..de296508bb
--- /dev/null
+++ b/gfx/gl/GLLibraryEGL.h
@@ -0,0 +1,993 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLLIBRARYEGL_H_
+#define GLLIBRARYEGL_H_
+
+#if defined(MOZ_X11)
+# include "mozilla/X11Util.h"
+#endif
+
+#include "base/platform_thread.h" // for PlatformThreadId
+#include "gfxEnv.h"
+#include "GLContext.h"
+#include "mozilla/EnumTypeTraits.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/StaticPtr.h"
+#include "nsISupports.h"
+#include "prlink.h"
+
+#include <bitset>
+#include <memory>
+#include <unordered_map>
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "mozilla/ProfilerLabels.h"
+# include "AndroidBuild.h"
+#endif
+
+#if defined(MOZ_X11)
+# define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
+#else
+# define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#endif
+
+struct ID3D11Device;
+
+extern "C" {
+struct AHardwareBuffer;
+}
+
+namespace angle {
+class Platform;
+}
+
+namespace mozilla {
+
+namespace gfx {
+class DataSourceSurface;
+}
+
+namespace gl {
+
+class SymbolLoader;
+
+PRLibrary* LoadApitraceLibrary();
+
+void BeforeEGLCall(const char* funcName);
+void AfterEGLCall(const char* funcName);
+
+class EglDisplay;
+/**
+ * Known GL extensions that can be queried by
+ * IsExtensionSupported. The results of this are cached, and as
+ * such it's safe to use this even in performance critical code.
+ * If you add to this array, remember to add to the string names
+ * in GLLibraryEGL.cpp.
+ */
+enum class EGLLibExtension {
+ ANDROID_get_native_client_buffer,
+ ANGLE_device_creation,
+ ANGLE_device_creation_d3d11,
+ ANGLE_platform_angle,
+ ANGLE_platform_angle_d3d,
+ EXT_device_enumeration,
+ EXT_device_query,
+ EXT_platform_device,
+ MESA_platform_surfaceless,
+ Max
+};
+
+/**
+ * Known GL extensions that can be queried by
+ * IsExtensionSupported. The results of this are cached, and as
+ * such it's safe to use this even in performance critical code.
+ * If you add to this array, remember to add to the string names
+ * in GLLibraryEGL.cpp.
+ */
+enum class EGLExtension {
+ KHR_image_base,
+ KHR_image_pixmap,
+ KHR_gl_texture_2D_image,
+ ANGLE_surface_d3d_texture_2d_share_handle,
+ EXT_create_context_robustness,
+ KHR_image,
+ KHR_fence_sync,
+ KHR_wait_sync,
+ ANDROID_native_fence_sync,
+ EGL_ANDROID_image_crop,
+ ANGLE_d3d_share_handle_client_buffer,
+ KHR_create_context,
+ KHR_stream,
+ KHR_stream_consumer_gltexture,
+ NV_stream_consumer_gltexture_yuv,
+ ANGLE_stream_producer_d3d_texture,
+ KHR_surfaceless_context,
+ KHR_create_context_no_error,
+ MOZ_create_context_provoking_vertex_dont_care,
+ EXT_swap_buffers_with_damage,
+ KHR_swap_buffers_with_damage,
+ EXT_buffer_age,
+ KHR_partial_update,
+ NV_robustness_video_memory_purge,
+ EXT_image_dma_buf_import,
+ EXT_image_dma_buf_import_modifiers,
+ MESA_image_dma_buf_export,
+ KHR_no_config_context,
+ Max
+};
+
+// -
+
+class GLLibraryEGL final {
+ friend class EglDisplay;
+
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
+
+ private:
+ PRLibrary* mEGLLibrary = nullptr;
+ PRLibrary* mGLLibrary = nullptr;
+ bool mIsANGLE = false;
+ std::bitset<UnderlyingValue(EGLLibExtension::Max)> mAvailableExtensions;
+ std::weak_ptr<EglDisplay> mDefaultDisplay;
+ std::unordered_map<EGLDisplay, std::weak_ptr<EglDisplay>> mActiveDisplays;
+
+ public:
+ static RefPtr<GLLibraryEGL> Get(nsACString* const out_failureId);
+ static void Shutdown();
+
+ private:
+ ~GLLibraryEGL() = default;
+
+ static StaticMutex sMutex;
+ static StaticRefPtr<GLLibraryEGL> sInstance MOZ_GUARDED_BY(sMutex);
+
+ bool Init(nsACString* const out_failureId);
+ void InitLibExtensions();
+
+ std::shared_ptr<EglDisplay> CreateDisplayLocked(
+ bool forceAccel, nsACString* const out_failureId,
+ const StaticMutexAutoLock& aProofOfLock);
+
+ public:
+ Maybe<SymbolLoader> GetSymbolLoader() const;
+
+ std::shared_ptr<EglDisplay> CreateDisplay(bool forceAccel,
+ nsACString* const out_failureId);
+ std::shared_ptr<EglDisplay> CreateDisplay(ID3D11Device*);
+ std::shared_ptr<EglDisplay> DefaultDisplay(nsACString* const out_failureId);
+
+ bool IsExtensionSupported(EGLLibExtension aKnownExtension) const {
+ return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
+ }
+
+ void MarkExtensionUnsupported(EGLLibExtension aKnownExtension) {
+ mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
+ }
+
+ bool IsANGLE() const { return mIsANGLE; }
+
+ // -
+ // PFN wrappers
+
+#ifdef MOZ_WIDGET_ANDROID
+# define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
+#else
+# define PROFILE_CALL
+#endif
+
+#ifndef MOZ_FUNCTION_NAME
+# ifdef __GNUC__
+# define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
+# elif defined(_MSC_VER)
+# define MOZ_FUNCTION_NAME __FUNCTION__
+# else
+# define MOZ_FUNCTION_NAME \
+ __func__ // defined in C99, supported in various C++ compilers. Just raw
+ // function name.
+# endif
+#endif
+
+#ifdef DEBUG
+# define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME);
+# define AFTER_CALL AfterEGLCall(MOZ_FUNCTION_NAME);
+#else
+# define BEFORE_CALL
+# define AFTER_CALL
+#endif
+
+#define WRAP(X) \
+ PROFILE_CALL \
+ BEFORE_CALL \
+ const auto ret = mSymbols.X; \
+ AFTER_CALL \
+ return ret
+
+ public:
+ EGLDisplay fGetDisplay(void* display_id) const {
+ WRAP(fGetDisplay(display_id));
+ }
+
+ EGLDisplay fGetPlatformDisplay(EGLenum platform, void* native_display,
+ const EGLAttrib* attrib_list) const {
+ WRAP(fGetPlatformDisplay(platform, native_display, attrib_list));
+ }
+
+ EGLSurface fGetCurrentSurface(EGLint id) const {
+ WRAP(fGetCurrentSurface(id));
+ }
+
+ EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); }
+
+ EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); }
+
+ EGLint fGetError() const { WRAP(fGetError()); }
+
+ EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); }
+
+ EGLCastToRelevantPtr fGetProcAddress(const char* procname) const {
+ WRAP(fGetProcAddress(procname));
+ }
+
+ // ANGLE_device_creation
+ EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device,
+ const EGLAttrib* attrib_list) const {
+ WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list));
+ }
+
+ EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) {
+ WRAP(fReleaseDeviceANGLE(device));
+ }
+
+ // ANDROID_get_native_client_buffer
+ EGLClientBuffer fGetNativeClientBufferANDROID(
+ const struct AHardwareBuffer* buffer) {
+ WRAP(fGetNativeClientBufferANDROID(buffer));
+ }
+
+ private:
+ EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); }
+
+ // -
+
+ mutable Mutex mMutex = Mutex{"GLLibraryEGL::mMutex"};
+ mutable std::unordered_map<EGLContext, PlatformThreadId>
+ mOwningThreadByContext MOZ_GUARDED_BY(mMutex);
+
+ EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
+ EGLContext ctx) const {
+ const bool CHECK_CONTEXT_OWNERSHIP = true;
+ if (CHECK_CONTEXT_OWNERSHIP) {
+ const MutexAutoLock lock(mMutex);
+ const auto tid = PlatformThread::CurrentId();
+ const auto prevCtx = fGetCurrentContext();
+
+ if (prevCtx) {
+ mOwningThreadByContext[prevCtx] = 0;
+ }
+ if (ctx) {
+ auto& ctxOwnerThread = mOwningThreadByContext[ctx];
+ if (ctxOwnerThread && ctxOwnerThread != tid) {
+ gfxCriticalError()
+ << "EGLContext#" << ctx << " is owned by/Current on"
+ << " thread#" << ctxOwnerThread << " but MakeCurrent requested on"
+ << " thread#" << tid << "!";
+ if (gfxEnv::MOZ_EGL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) {
+ MOZ_CRASH("MOZ_EGL_RELEASE_ASSERT_CONTEXT_OWNERSHIP");
+ }
+ return false;
+ }
+ ctxOwnerThread = tid;
+ }
+ }
+
+ // Always reset the TLS current context.
+ // If we're called by TLS-caching MakeCurrent, after we return true,
+ // the caller will set the TLS correctly anyway.
+ GLContext::ResetTLSCurrentContext();
+
+ WRAP(fMakeCurrent(dpy, draw, read, ctx));
+ }
+
+ // -
+
+ EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const {
+ {
+ const MutexAutoLock lock(mMutex);
+ mOwningThreadByContext.erase(ctx);
+ }
+
+ WRAP(fDestroyContext(dpy, ctx));
+ }
+
+ EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config,
+ EGLContext share_context,
+ const EGLint* attrib_list) const {
+ WRAP(fCreateContext(dpy, config, share_context, attrib_list));
+ }
+
+ EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const {
+ WRAP(fDestroySurface(dpy, surface));
+ }
+
+ public:
+ EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint* attrib_list) const {
+ WRAP(fCreateWindowSurface(dpy, config, win, attrib_list));
+ }
+
+ private:
+ EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
+ const EGLint* attrib_list) const {
+ WRAP(fCreatePbufferSurface(dpy, config, attrib_list));
+ }
+
+ EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
+ EGLClientBuffer buffer,
+ EGLConfig config,
+ const EGLint* attrib_list) const {
+ WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
+ attrib_list));
+ }
+
+ EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint* attrib_list) const {
+ WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list));
+ }
+
+ EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const {
+ WRAP(fInitialize(dpy, major, minor));
+ }
+
+ EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list,
+ EGLConfig* configs, EGLint config_size,
+ EGLint* num_config) const {
+ WRAP(fChooseConfig(dpy, attrib_list, configs, config_size, num_config));
+ }
+
+ EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint* value) const {
+ WRAP(fGetConfigAttrib(dpy, config, attribute, value));
+ }
+
+ EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
+ EGLint* num_config) const {
+ WRAP(fGetConfigs(dpy, configs, config_size, num_config));
+ }
+
+ EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const {
+ WRAP(fSwapBuffers(dpy, surface));
+ }
+
+ EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
+ EGLNativePixmapType target) const {
+ WRAP(fCopyBuffers(dpy, surface, target));
+ }
+
+ public:
+ const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const {
+ WRAP(fQueryString(dpy, name));
+ }
+
+ private:
+ EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
+ EGLint* value) const {
+ WRAP(fQueryContext(dpy, ctx, attribute, value));
+ }
+
+ EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer) const {
+ WRAP(fBindTexImage(dpy, surface, buffer));
+ }
+
+ EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer) const {
+ WRAP(fReleaseTexImage(dpy, surface, buffer));
+ }
+
+ EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const {
+ WRAP(fSwapInterval(dpy, interval));
+ }
+
+ EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint* attrib_list) const {
+ WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list));
+ }
+
+ EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const {
+ WRAP(fDestroyImageKHR(dpy, image));
+ }
+
+ EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
+ EGLint* value) const {
+ WRAP(fQuerySurface(dpy, surface, attribute, value));
+ }
+
+ EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, void** value) const {
+ WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value));
+ }
+
+ EGLSync fCreateSync(EGLDisplay dpy, EGLenum type,
+ const EGLint* attrib_list) const {
+ WRAP(fCreateSyncKHR(dpy, type, attrib_list));
+ }
+
+ EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const {
+ WRAP(fDestroySyncKHR(dpy, sync));
+ }
+
+ EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags,
+ EGLTime timeout) const {
+ WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout));
+ }
+
+ EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute,
+ EGLint* value) const {
+ WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value));
+ }
+
+ EGLint fWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) const {
+ WRAP(fWaitSyncKHR(dpy, sync, flags));
+ }
+
+ EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const {
+ WRAP(fDupNativeFenceFDANDROID(dpy, sync));
+ }
+
+ // KHR_stream
+ EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy,
+ const EGLint* attrib_list) const {
+ WRAP(fCreateStreamKHR(dpy, attrib_list));
+ }
+
+ EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const {
+ WRAP(fDestroyStreamKHR(dpy, stream));
+ }
+
+ EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint* value) const {
+ WRAP(fQueryStreamKHR(dpy, stream, attribute, value));
+ }
+
+ // KHR_stream_consumer_gltexture
+ EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
+ EGLStreamKHR stream) const {
+ WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream));
+ }
+
+ EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy,
+ EGLStreamKHR stream) const {
+ WRAP(fStreamConsumerAcquireKHR(dpy, stream));
+ }
+
+ EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy,
+ EGLStreamKHR stream) const {
+ WRAP(fStreamConsumerReleaseKHR(dpy, stream));
+ }
+
+ // EXT_device_query
+ EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute,
+ EGLAttrib* value) const {
+ WRAP(fQueryDisplayAttribEXT(dpy, attribute, value));
+ }
+
+ public:
+ EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute,
+ EGLAttrib* value) const {
+ WRAP(fQueryDeviceAttribEXT(device, attribute, value));
+ }
+
+ const char* fQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name) {
+ WRAP(fQueryDeviceStringEXT(device, name));
+ }
+
+ private:
+ // NV_stream_consumer_gltexture_yuv
+ EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
+ EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
+ WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list));
+ }
+
+ // ANGLE_stream_producer_d3d_texture
+ EGLBoolean fCreateStreamProducerD3DTextureANGLE(
+ EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
+ WRAP(fCreateStreamProducerD3DTextureANGLE(dpy, stream, attrib_list));
+ }
+
+ EGLBoolean fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
+ void* texture,
+ const EGLAttrib* attrib_list) const {
+ WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list));
+ }
+
+ // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
+ EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface,
+ const EGLint* rects, EGLint n_rects) {
+ WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects));
+ }
+
+ // EGL_KHR_partial_update
+ EGLBoolean fSetDamageRegion(EGLDisplay dpy, EGLSurface surface,
+ const EGLint* rects, EGLint n_rects) {
+ WRAP(fSetDamageRegion(dpy, surface, rects, n_rects));
+ }
+ // EGL_MESA_image_dma_buf_export
+ EGLBoolean fExportDMABUFImageQuery(EGLDisplay dpy, EGLImage image,
+ int* fourcc, int* num_planes,
+ uint64_t* modifiers) {
+ WRAP(
+ fExportDMABUFImageQueryMESA(dpy, image, fourcc, num_planes, modifiers));
+ }
+ EGLBoolean fExportDMABUFImage(EGLDisplay dpy, EGLImage image, int* fds,
+ EGLint* strides, EGLint* offsets) {
+ WRAP(fExportDMABUFImageMESA(dpy, image, fds, strides, offsets));
+ }
+
+ public:
+ // EGL_EXT_device_enumeration
+ EGLBoolean fQueryDevicesEXT(EGLint max_devices, EGLDeviceEXT* devices,
+ EGLint* num_devices) {
+ WRAP(fQueryDevicesEXT(max_devices, devices, num_devices));
+ }
+
+#undef WRAP
+
+#undef WRAP
+#undef PROFILE_CALL
+#undef BEFORE_CALL
+#undef AFTER_CALL
+#undef MOZ_FUNCTION_NAME
+
+ ////
+
+ private:
+ struct {
+ EGLCastToRelevantPtr(GLAPIENTRY* fGetProcAddress)(const char* procname);
+ EGLDisplay(GLAPIENTRY* fGetDisplay)(void* display_id);
+ EGLDisplay(GLAPIENTRY* fGetPlatformDisplay)(EGLenum platform,
+ void* native_display,
+ const EGLAttrib* attrib_list);
+ EGLBoolean(GLAPIENTRY* fTerminate)(EGLDisplay dpy);
+ EGLSurface(GLAPIENTRY* fGetCurrentSurface)(EGLint);
+ EGLContext(GLAPIENTRY* fGetCurrentContext)(void);
+ EGLBoolean(GLAPIENTRY* fMakeCurrent)(EGLDisplay dpy, EGLSurface draw,
+ EGLSurface read, EGLContext ctx);
+ EGLBoolean(GLAPIENTRY* fDestroyContext)(EGLDisplay dpy, EGLContext ctx);
+ EGLContext(GLAPIENTRY* fCreateContext)(EGLDisplay dpy, EGLConfig config,
+ EGLContext share_context,
+ const EGLint* attrib_list);
+ EGLBoolean(GLAPIENTRY* fDestroySurface)(EGLDisplay dpy, EGLSurface surface);
+ EGLSurface(GLAPIENTRY* fCreateWindowSurface)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativeWindowType win,
+ const EGLint* attrib_list);
+ EGLSurface(GLAPIENTRY* fCreatePbufferSurface)(EGLDisplay dpy,
+ EGLConfig config,
+ const EGLint* attrib_list);
+ EGLSurface(GLAPIENTRY* fCreatePbufferFromClientBuffer)(
+ EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
+ EGLConfig config, const EGLint* attrib_list);
+ EGLSurface(GLAPIENTRY* fCreatePixmapSurface)(EGLDisplay dpy,
+ EGLConfig config,
+ EGLNativePixmapType pixmap,
+ const EGLint* attrib_list);
+ EGLBoolean(GLAPIENTRY* fBindAPI)(EGLenum api);
+ EGLBoolean(GLAPIENTRY* fInitialize)(EGLDisplay dpy, EGLint* major,
+ EGLint* minor);
+ EGLBoolean(GLAPIENTRY* fChooseConfig)(EGLDisplay dpy,
+ const EGLint* attrib_list,
+ EGLConfig* configs,
+ EGLint config_size,
+ EGLint* num_config);
+ EGLint(GLAPIENTRY* fGetError)(void);
+ EGLBoolean(GLAPIENTRY* fGetConfigAttrib)(EGLDisplay dpy, EGLConfig config,
+ EGLint attribute, EGLint* value);
+ EGLBoolean(GLAPIENTRY* fGetConfigs)(EGLDisplay dpy, EGLConfig* configs,
+ EGLint config_size, EGLint* num_config);
+ EGLBoolean(GLAPIENTRY* fWaitNative)(EGLint engine);
+ EGLBoolean(GLAPIENTRY* fSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
+ EGLBoolean(GLAPIENTRY* fCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
+ EGLNativePixmapType target);
+ const GLubyte*(GLAPIENTRY* fQueryString)(EGLDisplay, EGLint name);
+ EGLBoolean(GLAPIENTRY* fQueryContext)(EGLDisplay dpy, EGLContext ctx,
+ EGLint attribute, EGLint* value);
+ EGLBoolean(GLAPIENTRY* fBindTexImage)(EGLDisplay, EGLSurface surface,
+ EGLint buffer);
+ EGLBoolean(GLAPIENTRY* fReleaseTexImage)(EGLDisplay, EGLSurface surface,
+ EGLint buffer);
+ EGLBoolean(GLAPIENTRY* fSwapInterval)(EGLDisplay dpy, EGLint interval);
+ EGLImage(GLAPIENTRY* fCreateImageKHR)(EGLDisplay dpy, EGLContext ctx,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const EGLint* attrib_list);
+ EGLBoolean(GLAPIENTRY* fDestroyImageKHR)(EGLDisplay dpy, EGLImage image);
+ EGLBoolean(GLAPIENTRY* fQuerySurface)(EGLDisplay dpy, EGLSurface surface,
+ EGLint attribute, EGLint* value);
+ EGLBoolean(GLAPIENTRY* fQuerySurfacePointerANGLE)(EGLDisplay dpy,
+ EGLSurface surface,
+ EGLint attribute,
+ void** value);
+ EGLSync(GLAPIENTRY* fCreateSyncKHR)(EGLDisplay dpy, EGLenum type,
+ const EGLint* attrib_list);
+ EGLBoolean(GLAPIENTRY* fDestroySyncKHR)(EGLDisplay dpy, EGLSync sync);
+ EGLint(GLAPIENTRY* fClientWaitSyncKHR)(EGLDisplay dpy, EGLSync sync,
+ EGLint flags, EGLTime timeout);
+ EGLBoolean(GLAPIENTRY* fGetSyncAttribKHR)(EGLDisplay dpy, EGLSync sync,
+ EGLint attribute, EGLint* value);
+ EGLint(GLAPIENTRY* fWaitSyncKHR)(EGLDisplay dpy, EGLSync sync,
+ EGLint flags);
+ EGLint(GLAPIENTRY* fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
+ // KHR_stream
+ EGLStreamKHR(GLAPIENTRY* fCreateStreamKHR)(EGLDisplay dpy,
+ const EGLint* attrib_list);
+ EGLBoolean(GLAPIENTRY* fDestroyStreamKHR)(EGLDisplay dpy,
+ EGLStreamKHR stream);
+ EGLBoolean(GLAPIENTRY* fQueryStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream,
+ EGLenum attribute, EGLint* value);
+ // KHR_stream_consumer_gltexture
+ EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalKHR)(
+ EGLDisplay dpy, EGLStreamKHR stream);
+ EGLBoolean(GLAPIENTRY* fStreamConsumerAcquireKHR)(EGLDisplay dpy,
+ EGLStreamKHR stream);
+ EGLBoolean(GLAPIENTRY* fStreamConsumerReleaseKHR)(EGLDisplay dpy,
+ EGLStreamKHR stream);
+ // EXT_device_query
+ EGLBoolean(GLAPIENTRY* fQueryDisplayAttribEXT)(EGLDisplay dpy,
+ EGLint attribute,
+ EGLAttrib* value);
+ EGLBoolean(GLAPIENTRY* fQueryDeviceAttribEXT)(EGLDeviceEXT device,
+ EGLint attribute,
+ EGLAttrib* value);
+ const char*(GLAPIENTRY* fQueryDeviceStringEXT)(EGLDeviceEXT device,
+ EGLint name);
+
+ // NV_stream_consumer_gltexture_yuv
+ EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalAttribsNV)(
+ EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list);
+ // ANGLE_stream_producer_d3d_texture
+ EGLBoolean(GLAPIENTRY* fCreateStreamProducerD3DTextureANGLE)(
+ EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list);
+ EGLBoolean(GLAPIENTRY* fStreamPostD3DTextureANGLE)(
+ EGLDisplay dpy, EGLStreamKHR stream, void* texture,
+ const EGLAttrib* attrib_list);
+ // ANGLE_device_creation
+ EGLDeviceEXT(GLAPIENTRY* fCreateDeviceANGLE)(EGLint device_type,
+ void* native_device,
+ const EGLAttrib* attrib_list);
+ EGLBoolean(GLAPIENTRY* fReleaseDeviceANGLE)(EGLDeviceEXT device);
+ // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
+ EGLBoolean(GLAPIENTRY* fSwapBuffersWithDamage)(EGLDisplay dpy,
+ EGLSurface surface,
+ const EGLint* rects,
+ EGLint n_rects);
+ // EGL_KHR_partial_update
+ EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface,
+ const EGLint* rects,
+ EGLint n_rects);
+ EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)(
+ const struct AHardwareBuffer* buffer);
+
+ // EGL_MESA_image_dma_buf_export
+ EGLBoolean(GLAPIENTRY* fExportDMABUFImageQueryMESA)(EGLDisplay dpy,
+ EGLImage image,
+ int* fourcc,
+ int* num_planes,
+ uint64_t* modifiers);
+ EGLBoolean(GLAPIENTRY* fExportDMABUFImageMESA)(EGLDisplay dpy,
+ EGLImage image, int* fds,
+ EGLint* strides,
+ EGLint* offsets);
+
+ EGLBoolean(GLAPIENTRY* fQueryDevicesEXT)(EGLint max_devices,
+ EGLDeviceEXT* devices,
+ EGLint* num_devices);
+
+ } mSymbols = {};
+};
+
+static bool ShouldLeakEglDisplay() {
+ // We are seeing crashes in eglTerminate on the Samsung S22 family of devices
+ // running Android 14, so we leak the EGLDisplay rather than call
+ // eglTerminate.
+#ifdef MOZ_WIDGET_ANDROID
+ if (jni::GetAPIVersion() >= 34) {
+ const auto board = java::sdk::Build::BOARD()->ToString();
+ if (board.EqualsASCII("s5e9925")) {
+ return true;
+ }
+ }
+#endif
+ return false;
+}
+
+class EglDisplay final {
+ public:
+ const RefPtr<GLLibraryEGL> mLib;
+ const EGLDisplay mDisplay;
+ const bool mIsWARP;
+
+ private:
+ std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions;
+
+ struct PrivateUseOnly final {};
+
+ public:
+ static std::shared_ptr<EglDisplay> Create(
+ GLLibraryEGL&, EGLDisplay, bool isWarp,
+ const StaticMutexAutoLock& aProofOfLock);
+
+ // Only `public` for make_shared.
+ EglDisplay(const PrivateUseOnly&, GLLibraryEGL&, EGLDisplay, bool isWarp);
+
+ public:
+ ~EglDisplay();
+
+ bool IsExtensionSupported(EGLExtension aKnownExtension) const {
+ return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
+ }
+
+ void MarkExtensionUnsupported(EGLExtension aKnownExtension) {
+ mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
+ }
+
+ void DumpEGLConfig(EGLConfig) const;
+ void DumpEGLConfigs() const;
+
+ void Shutdown();
+
+ // -
+
+ bool HasKHRImageBase() const {
+ return IsExtensionSupported(EGLExtension::KHR_image) ||
+ IsExtensionSupported(EGLExtension::KHR_image_base);
+ }
+
+ bool HasKHRImagePixmap() const {
+ return IsExtensionSupported(EGLExtension::KHR_image) ||
+ IsExtensionSupported(EGLExtension::KHR_image_pixmap);
+ }
+
+ // -
+
+ EGLBoolean fTerminate() {
+ static const bool shouldLeak = ShouldLeakEglDisplay();
+ if (shouldLeak) {
+ return LOCAL_EGL_TRUE;
+ }
+ return mLib->fTerminate(mDisplay);
+ }
+
+ EGLBoolean fMakeCurrent(EGLSurface draw, EGLSurface read,
+ EGLContext ctx) const {
+ return mLib->fMakeCurrent(mDisplay, draw, read, ctx);
+ }
+
+ EGLBoolean fDestroyContext(EGLContext ctx) const {
+ return mLib->fDestroyContext(mDisplay, ctx);
+ }
+
+ EGLContext fCreateContext(EGLConfig config, EGLContext share_context,
+ const EGLint* attrib_list) const {
+ return mLib->fCreateContext(mDisplay, config, share_context, attrib_list);
+ }
+
+ EGLBoolean fDestroySurface(EGLSurface surface) const {
+ return mLib->fDestroySurface(mDisplay, surface);
+ }
+
+ EGLSurface fCreateWindowSurface(EGLConfig config, EGLNativeWindowType win,
+ const EGLint* attrib_list) const {
+ return mLib->fCreateWindowSurface(mDisplay, config, win, attrib_list);
+ }
+
+ EGLSurface fCreatePbufferSurface(EGLConfig config,
+ const EGLint* attrib_list) const {
+ return mLib->fCreatePbufferSurface(mDisplay, config, attrib_list);
+ }
+
+ EGLSurface fCreatePbufferFromClientBuffer(EGLenum buftype,
+ EGLClientBuffer buffer,
+ EGLConfig config,
+ const EGLint* attrib_list) const {
+ return mLib->fCreatePbufferFromClientBuffer(mDisplay, buftype, buffer,
+ config, attrib_list);
+ }
+
+ EGLBoolean fChooseConfig(const EGLint* attrib_list, EGLConfig* configs,
+ EGLint config_size, EGLint* num_config) const {
+ return mLib->fChooseConfig(mDisplay, attrib_list, configs, config_size,
+ num_config);
+ }
+
+ EGLBoolean fGetConfigAttrib(EGLConfig config, EGLint attribute,
+ EGLint* value) const {
+ return mLib->fGetConfigAttrib(mDisplay, config, attribute, value);
+ }
+
+ EGLBoolean fGetConfigs(EGLConfig* configs, EGLint config_size,
+ EGLint* num_config) const {
+ return mLib->fGetConfigs(mDisplay, configs, config_size, num_config);
+ }
+
+ EGLBoolean fSwapBuffers(EGLSurface surface) const {
+ return mLib->fSwapBuffers(mDisplay, surface);
+ }
+
+ EGLBoolean fBindTexImage(EGLSurface surface, EGLint buffer) const {
+ return mLib->fBindTexImage(mDisplay, surface, buffer);
+ }
+
+ EGLBoolean fReleaseTexImage(EGLSurface surface, EGLint buffer) const {
+ return mLib->fReleaseTexImage(mDisplay, surface, buffer);
+ }
+
+ EGLBoolean fSwapInterval(EGLint interval) const {
+ return mLib->fSwapInterval(mDisplay, interval);
+ }
+
+ EGLImage fCreateImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
+ const EGLint* attribList) const {
+ MOZ_ASSERT(HasKHRImageBase());
+ return mLib->fCreateImage(mDisplay, ctx, target, buffer, attribList);
+ }
+
+ EGLBoolean fDestroyImage(EGLImage image) const {
+ MOZ_ASSERT(HasKHRImageBase());
+ return mLib->fDestroyImage(mDisplay, image);
+ }
+
+ EGLBoolean fQuerySurface(EGLSurface surface, EGLint attribute,
+ EGLint* value) const {
+ return mLib->fQuerySurface(mDisplay, surface, attribute, value);
+ }
+
+ EGLBoolean fQuerySurfacePointerANGLE(EGLSurface surface, EGLint attribute,
+ void** value) const {
+ MOZ_ASSERT(IsExtensionSupported(
+ EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle));
+ return mLib->fQuerySurfacePointerANGLE(mDisplay, surface, attribute, value);
+ }
+
+ EGLSync fCreateSync(EGLenum type, const EGLint* attrib_list) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
+ return mLib->fCreateSync(mDisplay, type, attrib_list);
+ }
+
+ EGLBoolean fDestroySync(EGLSync sync) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
+ return mLib->fDestroySync(mDisplay, sync);
+ }
+
+ EGLint fClientWaitSync(EGLSync sync, EGLint flags, EGLTime timeout) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
+ return mLib->fClientWaitSync(mDisplay, sync, flags, timeout);
+ }
+
+ EGLBoolean fGetSyncAttrib(EGLSync sync, EGLint attribute,
+ EGLint* value) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
+ return mLib->fGetSyncAttrib(mDisplay, sync, attribute, value);
+ }
+
+ EGLint fWaitSync(EGLSync sync, EGLint flags) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_wait_sync));
+ return mLib->fWaitSync(mDisplay, sync, flags);
+ }
+
+ EGLint fDupNativeFenceFDANDROID(EGLSync sync) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync));
+ return mLib->fDupNativeFenceFDANDROID(mDisplay, sync);
+ }
+
+ // EXT_device_query
+ EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const {
+ MOZ_ASSERT(mLib->IsExtensionSupported(EGLLibExtension::EXT_device_query));
+ return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value);
+ }
+
+ // KHR_stream
+ EGLStreamKHR fCreateStreamKHR(const EGLint* attrib_list) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
+ return mLib->fCreateStreamKHR(mDisplay, attrib_list);
+ }
+
+ EGLBoolean fDestroyStreamKHR(EGLStreamKHR stream) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
+ return mLib->fDestroyStreamKHR(mDisplay, stream);
+ }
+
+ EGLBoolean fQueryStreamKHR(EGLStreamKHR stream, EGLenum attribute,
+ EGLint* value) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
+ return mLib->fQueryStreamKHR(mDisplay, stream, attribute, value);
+ }
+
+ // KHR_stream_consumer_gltexture
+ EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
+ return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream);
+ }
+
+ EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
+ return mLib->fStreamConsumerAcquireKHR(mDisplay, stream);
+ }
+
+ EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
+ return mLib->fStreamConsumerReleaseKHR(mDisplay, stream);
+ }
+
+ // NV_stream_consumer_gltexture_yuv
+ EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
+ EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv));
+ return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream,
+ attrib_list);
+ }
+
+ // ANGLE_stream_producer_d3d_texture
+ EGLBoolean fCreateStreamProducerD3DTextureANGLE(
+ EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
+ return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream,
+ attrib_list);
+ }
+
+ EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture,
+ const EGLAttrib* attrib_list) const {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
+ return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture,
+ attrib_list);
+ }
+
+ // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
+ EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects,
+ EGLint n_rects) {
+ MOZ_ASSERT(
+ IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage) ||
+ IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage));
+ return mLib->fSwapBuffersWithDamage(mDisplay, surface, rects, n_rects);
+ }
+
+ // EGL_KHR_partial_update
+ EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects,
+ EGLint n_rects) {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update));
+ return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects);
+ }
+
+ EGLBoolean fExportDMABUFImageQuery(EGLImage image, int* fourcc,
+ int* num_planes,
+ uint64_t* modifiers) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export));
+ return mLib->fExportDMABUFImageQuery(mDisplay, image, fourcc, num_planes,
+ modifiers);
+ }
+ EGLBoolean fExportDMABUFImage(EGLImage image, int* fds, EGLint* strides,
+ EGLint* offsets) const {
+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export));
+ return mLib->fExportDMABUFImage(mDisplay, image, fds, strides, offsets);
+ }
+};
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* GLLIBRARYEGL_H_ */
diff --git a/gfx/gl/GLLibraryLoader.cpp b/gfx/gl/GLLibraryLoader.cpp
new file mode 100644
index 0000000000..e73f312d29
--- /dev/null
+++ b/gfx/gl/GLLibraryLoader.cpp
@@ -0,0 +1,74 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLLibraryLoader.h"
+
+#include <regex>
+
+#include "mozilla/gfx/Logging.h"
+#include "nsDebug.h"
+
+#ifdef WIN32
+# include <windows.h>
+#endif
+
+namespace mozilla {
+namespace gl {
+
+void ClearSymbols(const SymLoadStruct* const firstStruct) {
+ for (auto itr = firstStruct; itr->symPointer; ++itr) {
+ *itr->symPointer = nullptr;
+ }
+}
+
+bool SymbolLoader::LoadSymbols(const SymLoadStruct* const firstStruct,
+ const bool warnOnFailures) const {
+ bool ok = true;
+
+ for (auto itr = firstStruct; itr->symPointer; ++itr) {
+ *itr->symPointer = nullptr;
+
+ for (const auto& s : itr->symNames) {
+ if (!s) break;
+
+ const auto p = GetProcAddress(s);
+ if (p) {
+ *itr->symPointer = p;
+ break;
+ }
+ }
+
+ if (!*itr->symPointer) {
+ if (warnOnFailures) {
+ printf_stderr("Can't find symbol '%s'.\n", itr->symNames[0]);
+ }
+ ok = false;
+ }
+ }
+
+ return ok;
+}
+
+// -
+
+PRFuncPtr SymbolLoader::GetProcAddress(const char* const name) const {
+#ifdef DEBUG
+ static const std::regex kRESymbol("[a-z].*");
+ if (!std::regex_match(name, kRESymbol)) {
+ gfxCriticalError() << "Bad symbol name : " << name;
+ }
+#endif
+
+ PRFuncPtr ret = nullptr;
+ if (!ret && mLib) {
+ ret = PR_FindFunctionSymbol(mLib, name);
+ }
+ if (!ret && mPfn) {
+ ret = mPfn(name);
+ }
+ return ret;
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLLibraryLoader.h b/gfx/gl/GLLibraryLoader.h
new file mode 100644
index 0000000000..e44e862f03
--- /dev/null
+++ b/gfx/gl/GLLibraryLoader.h
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLLIBRARYLOADER_H_
+#define GLLIBRARYLOADER_H_
+
+#include <array>
+#include <stdio.h>
+
+#include "GLDefs.h"
+#include "nscore.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/SharedLibrary.h"
+
+namespace mozilla {
+namespace gl {
+
+struct SymLoadStruct final {
+ PRFuncPtr* symPointer;
+ std::array<const char*, 6> symNames;
+};
+
+void ClearSymbols(const SymLoadStruct* firstStruct);
+
+class SymbolLoader final {
+ public:
+ typedef PRFuncPtr(GLAPIENTRY* GetProcAddressT)(const char*);
+
+ GetProcAddressT mPfn = nullptr; // Try this first, if not null.
+ PRLibrary* mLib = nullptr;
+
+ explicit SymbolLoader(void*(GLAPIENTRY* pfn)(const char*))
+ : mPfn(GetProcAddressT(pfn)) {
+ MOZ_ASSERT(mPfn);
+ }
+
+ explicit SymbolLoader(const GetProcAddressT pfn) : mPfn(pfn) {
+ MOZ_ASSERT(mPfn);
+ }
+
+ explicit SymbolLoader(PRLibrary& lib) : mLib(&lib) { MOZ_ASSERT(mLib); }
+
+ PRFuncPtr GetProcAddress(const char*) const;
+ bool LoadSymbols(const SymLoadStruct* firstStruct,
+ bool warnOnFailures = true) const;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GLLIBRARYLOADER_H_
diff --git a/gfx/gl/GLReadTexImageHelper.cpp b/gfx/gl/GLReadTexImageHelper.cpp
new file mode 100644
index 0000000000..d45f700f16
--- /dev/null
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -0,0 +1,628 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLReadTexImageHelper.h"
+
+#include <utility>
+
+#include "GLContext.h"
+#include "OGLShaderProgram.h"
+#include "ScopedGLHelpers.h"
+#include "gfx2DGlue.h"
+#include "gfxColor.h"
+#include "gfxTypes.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/gfx/Swizzle.h"
+
+namespace mozilla {
+namespace gl {
+
+using namespace mozilla::gfx;
+
+GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl) : mGL(gl) {
+ mPrograms[0] = 0;
+ mPrograms[1] = 0;
+ mPrograms[2] = 0;
+ mPrograms[3] = 0;
+}
+
+GLReadTexImageHelper::~GLReadTexImageHelper() {
+ if (!mGL->MakeCurrent()) return;
+
+ mGL->fDeleteProgram(mPrograms[0]);
+ mGL->fDeleteProgram(mPrograms[1]);
+ mGL->fDeleteProgram(mPrograms[2]);
+ mGL->fDeleteProgram(mPrograms[3]);
+}
+
+static const GLchar readTextureImageVS[] =
+ "attribute vec2 aVertex;\n"
+ "attribute vec2 aTexCoord;\n"
+ "varying vec2 vTexCoord;\n"
+ "void main() { gl_Position = vec4(aVertex, 0, 1); vTexCoord = aTexCoord; }";
+
+static const GLchar readTextureImageFS_TEXTURE_2D[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform sampler2D uTexture;\n"
+ "void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
+
+static const GLchar readTextureImageFS_TEXTURE_2D_BGRA[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform sampler2D uTexture;\n"
+ "void main() { gl_FragColor = texture2D(uTexture, vTexCoord).bgra; }";
+
+static const GLchar readTextureImageFS_TEXTURE_EXTERNAL[] =
+ "#extension GL_OES_EGL_image_external : require\n"
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform samplerExternalOES uTexture;\n"
+ "void main() { gl_FragColor = texture2D(uTexture, vTexCoord); }";
+
+static const GLchar readTextureImageFS_TEXTURE_RECTANGLE[] =
+ "#extension GL_ARB_texture_rectangle\n"
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "varying vec2 vTexCoord;\n"
+ "uniform sampler2DRect uTexture;\n"
+ "void main() { gl_FragColor = texture2DRect(uTexture, vTexCoord).bgra; }";
+
+GLuint GLReadTexImageHelper::TextureImageProgramFor(GLenum aTextureTarget,
+ int aConfig) {
+ int variant = 0;
+ const GLchar* readTextureImageFS = nullptr;
+ if (aTextureTarget == LOCAL_GL_TEXTURE_2D) {
+ if (aConfig & mozilla::layers::ENABLE_TEXTURE_RB_SWAP) {
+ // Need to swizzle R/B.
+ readTextureImageFS = readTextureImageFS_TEXTURE_2D_BGRA;
+ variant = 1;
+ } else {
+ readTextureImageFS = readTextureImageFS_TEXTURE_2D;
+ variant = 0;
+ }
+ } else if (aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL) {
+ readTextureImageFS = readTextureImageFS_TEXTURE_EXTERNAL;
+ variant = 2;
+ } else if (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE) {
+ readTextureImageFS = readTextureImageFS_TEXTURE_RECTANGLE;
+ variant = 3;
+ }
+
+ /* This might be overkill, but assure that we don't access out-of-bounds */
+ MOZ_ASSERT((size_t)variant < ArrayLength(mPrograms));
+ if (!mPrograms[variant]) {
+ GLuint vs = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER);
+ const GLchar* vsSourcePtr = &readTextureImageVS[0];
+ mGL->fShaderSource(vs, 1, &vsSourcePtr, nullptr);
+ mGL->fCompileShader(vs);
+
+ GLuint fs = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER);
+ mGL->fShaderSource(fs, 1, &readTextureImageFS, nullptr);
+ mGL->fCompileShader(fs);
+
+ GLuint program = mGL->fCreateProgram();
+ mGL->fAttachShader(program, vs);
+ mGL->fAttachShader(program, fs);
+ mGL->fBindAttribLocation(program, 0, "aVertex");
+ mGL->fBindAttribLocation(program, 1, "aTexCoord");
+ mGL->fLinkProgram(program);
+
+ GLint success;
+ mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &success);
+
+ if (!success) {
+ mGL->fDeleteProgram(program);
+ program = 0;
+ }
+
+ mGL->fDeleteShader(vs);
+ mGL->fDeleteShader(fs);
+
+ mPrograms[variant] = program;
+ }
+
+ return mPrograms[variant];
+}
+
+bool GLReadTexImageHelper::DidGLErrorOccur(const char* str) {
+ GLenum error = mGL->fGetError();
+ if (error != LOCAL_GL_NO_ERROR) {
+ printf_stderr("GL ERROR: %s %s\n",
+ GLContext::GLErrorToString(error).c_str(), str);
+ return true;
+ }
+
+ return false;
+}
+
+bool GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType,
+ GLenum* out_readFormat, GLenum* out_readType) {
+ MOZ_ASSERT(out_readFormat);
+ MOZ_ASSERT(out_readType);
+
+ if (destFormat == LOCAL_GL_RGBA && destType == LOCAL_GL_UNSIGNED_BYTE) {
+ *out_readFormat = destFormat;
+ *out_readType = destType;
+ return true;
+ }
+
+ bool fallback = true;
+ if (gl->IsGLES()) {
+ GLenum auxFormat = 0;
+ GLenum auxType = 0;
+
+ gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT,
+ (GLint*)&auxFormat);
+ gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_TYPE, (GLint*)&auxType);
+
+ if (destFormat == auxFormat && destType == auxType) {
+ fallback = false;
+ }
+ } else {
+ switch (destFormat) {
+ case LOCAL_GL_RGB: {
+ if (destType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV) fallback = false;
+ break;
+ }
+ case LOCAL_GL_BGRA: {
+ if (destType == LOCAL_GL_UNSIGNED_BYTE ||
+ destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV) {
+ fallback = false;
+ }
+ break;
+ }
+ }
+ }
+
+ if (fallback) {
+ *out_readFormat = LOCAL_GL_RGBA;
+ *out_readType = LOCAL_GL_UNSIGNED_BYTE;
+ return false;
+ } else {
+ *out_readFormat = destFormat;
+ *out_readType = destType;
+ return true;
+ }
+}
+
+void SwapRAndBComponents(DataSourceSurface* surf) {
+ DataSourceSurface::MappedSurface map;
+ if (!surf->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
+ MOZ_ASSERT(false, "SwapRAndBComponents: Failed to map surface.");
+ return;
+ }
+ MOZ_ASSERT(map.mStride >= 0);
+
+ const size_t rowBytes = surf->GetSize().width * 4;
+ const size_t rowHole = map.mStride - rowBytes;
+
+ uint8_t* row = map.mData;
+ if (!row) {
+ MOZ_ASSERT(false,
+ "SwapRAndBComponents: Failed to get data from"
+ " DataSourceSurface.");
+ surf->Unmap();
+ return;
+ }
+
+ const size_t rows = surf->GetSize().height;
+ for (size_t i = 0; i < rows; i++) {
+ const uint8_t* rowEnd = row + rowBytes;
+
+ while (row != rowEnd) {
+ std::swap(row[0], row[2]);
+ row += 4;
+ }
+
+ row += rowHole;
+ }
+
+ surf->Unmap();
+}
+
+static int CalcRowStride(int width, int pixelSize, int alignment) {
+ MOZ_ASSERT(alignment);
+
+ int rowStride = width * pixelSize;
+ if (rowStride % alignment) { // Extra at the end of the line?
+ int alignmentCount = rowStride / alignment;
+ rowStride = (alignmentCount + 1) * alignment;
+ }
+ return rowStride;
+}
+
+static int GuessAlignment(int width, int pixelSize, int rowStride) {
+ int alignment = 8; // Max GLES allows.
+ while (CalcRowStride(width, pixelSize, alignment) != rowStride) {
+ alignment /= 2;
+ if (!alignment) {
+ NS_WARNING("Bad alignment for GLES. Will use temp surf for readback.");
+ return 0;
+ }
+ }
+ return alignment;
+}
+
+void ReadPixelsIntoBuffer(GLContext* gl, uint8_t* aData, int32_t aStride,
+ const IntSize& aSize, SurfaceFormat aFormat) {
+ gl->MakeCurrent();
+ MOZ_ASSERT(aSize.width != 0);
+ MOZ_ASSERT(aSize.height != 0);
+
+ bool hasAlpha =
+ aFormat == SurfaceFormat::B8G8R8A8 || aFormat == SurfaceFormat::R8G8B8A8;
+
+ int destPixelSize;
+ GLenum destFormat;
+ GLenum destType;
+
+ switch (aFormat) {
+ case SurfaceFormat::B8G8R8A8:
+ case SurfaceFormat::B8G8R8X8:
+ // Needs host (little) endian ARGB.
+ destFormat = LOCAL_GL_BGRA;
+ destType = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ break;
+ case SurfaceFormat::R8G8B8A8:
+ case SurfaceFormat::R8G8B8X8:
+ // Needs host (little) endian ABGR.
+ destFormat = LOCAL_GL_RGBA;
+ destType = LOCAL_GL_UNSIGNED_BYTE;
+ break;
+ case SurfaceFormat::R5G6B5_UINT16:
+ destFormat = LOCAL_GL_RGB;
+ destType = LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV;
+ break;
+ default:
+ MOZ_CRASH("GFX: Bad format, read pixels.");
+ }
+ destPixelSize = BytesPerPixel(aFormat);
+
+ MOZ_ASSERT(aSize.width * destPixelSize <= aStride);
+
+ GLenum readFormat = destFormat;
+ GLenum readType = destType;
+ bool needsTempSurf =
+ !GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType);
+
+ RefPtr<DataSourceSurface> tempSurf;
+ Maybe<DataSourceSurface::ScopedMap> tempMap;
+ uint8_t* data = aData;
+ SurfaceFormat readFormatGFX;
+
+ int readAlignment = GuessAlignment(aSize.width, destPixelSize, aStride);
+ if (!readAlignment) {
+ needsTempSurf = true;
+ }
+ if (needsTempSurf) {
+ if (GLContext::ShouldSpew()) {
+ NS_WARNING(
+ "Needing intermediary surface for ReadPixels. This will be slow!");
+ }
+
+ switch (readFormat) {
+ case LOCAL_GL_RGBA: {
+ readFormatGFX =
+ hasAlpha ? SurfaceFormat::R8G8B8A8 : SurfaceFormat::R8G8B8X8;
+ break;
+ }
+ case LOCAL_GL_BGRA: {
+ readFormatGFX =
+ hasAlpha ? SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
+ break;
+ }
+ case LOCAL_GL_RGB: {
+ MOZ_ASSERT(destPixelSize == 2);
+ MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV);
+ readFormatGFX = SurfaceFormat::R5G6B5_UINT16;
+ break;
+ }
+ default: {
+ MOZ_CRASH("GFX: Bad read format, read format.");
+ }
+ }
+
+ switch (readType) {
+ case LOCAL_GL_UNSIGNED_BYTE: {
+ MOZ_ASSERT(readFormat == LOCAL_GL_RGBA);
+ readAlignment = 1;
+ break;
+ }
+ case LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV: {
+ MOZ_ASSERT(readFormat == LOCAL_GL_BGRA);
+ readAlignment = 4;
+ break;
+ }
+ case LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV: {
+ MOZ_ASSERT(readFormat == LOCAL_GL_RGB);
+ readAlignment = 2;
+ break;
+ }
+ default: {
+ MOZ_CRASH("GFX: Bad read type, read type.");
+ }
+ }
+
+ int32_t stride = aSize.width * BytesPerPixel(readFormatGFX);
+ tempSurf = Factory::CreateDataSourceSurfaceWithStride(aSize, readFormatGFX,
+ stride);
+ if (NS_WARN_IF(!tempSurf)) {
+ return;
+ }
+
+ tempMap.emplace(tempSurf, DataSourceSurface::READ_WRITE);
+ if (NS_WARN_IF(!tempMap->IsMapped())) {
+ return;
+ }
+
+ data = tempMap->GetData();
+ }
+
+ MOZ_ASSERT(readAlignment);
+ MOZ_ASSERT(reinterpret_cast<uintptr_t>(data) % readAlignment == 0);
+
+ GLsizei width = aSize.width;
+ GLsizei height = aSize.height;
+
+ {
+ ScopedPackState safePackState(gl);
+ gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment);
+
+ gl->fReadPixels(0, 0, width, height, readFormat, readType, data);
+ }
+
+ if (tempMap) {
+ SwizzleData(tempMap->GetData(), tempMap->GetStride(), readFormatGFX, aData,
+ aStride, aFormat, aSize);
+ }
+}
+
+void ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) {
+ gl->MakeCurrent();
+
+ DataSourceSurface::ScopedMap map(dest, DataSourceSurface::WRITE);
+ ReadPixelsIntoBuffer(gl, map.GetData(), map.GetStride(), dest->GetSize(),
+ dest->GetFormat());
+}
+
+already_AddRefed<gfx::DataSourceSurface> YInvertImageSurface(
+ gfx::DataSourceSurface* aSurf, uint32_t aStride) {
+ RefPtr<DataSourceSurface> temp = Factory::CreateDataSourceSurfaceWithStride(
+ aSurf->GetSize(), aSurf->GetFormat(), aStride);
+ if (NS_WARN_IF(!temp)) {
+ return nullptr;
+ }
+
+ DataSourceSurface::MappedSurface map;
+ if (!temp->Map(DataSourceSurface::MapType::WRITE, &map)) {
+ return nullptr;
+ }
+
+ RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(
+ BackendType::CAIRO, map.mData, temp->GetSize(), map.mStride,
+ temp->GetFormat());
+ if (!dt) {
+ temp->Unmap();
+ return nullptr;
+ }
+
+ dt->SetTransform(Matrix::Scaling(1.0, -1.0) *
+ Matrix::Translation(0.0, aSurf->GetSize().height));
+ Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
+ dt->DrawSurface(
+ aSurf, rect, rect, DrawSurfaceOptions(),
+ DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
+ temp->Unmap();
+ return temp.forget();
+}
+
+already_AddRefed<DataSourceSurface> ReadBackSurface(GLContext* gl,
+ GLuint aTexture,
+ bool aYInvert,
+ SurfaceFormat aFormat) {
+ gl->MakeCurrent();
+ gl->fActiveTexture(LOCAL_GL_TEXTURE0);
+ gl->fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
+
+ IntSize size;
+ gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_WIDTH,
+ &size.width);
+ gl->fGetTexLevelParameteriv(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_TEXTURE_HEIGHT,
+ &size.height);
+
+ RefPtr<DataSourceSurface> surf = Factory::CreateDataSourceSurfaceWithStride(
+ size, SurfaceFormat::B8G8R8A8,
+ GetAlignedStride<4>(size.width, BytesPerPixel(SurfaceFormat::B8G8R8A8)));
+
+ if (NS_WARN_IF(!surf)) {
+ return nullptr;
+ }
+
+ uint32_t currentPackAlignment = 0;
+ gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, (GLint*)&currentPackAlignment);
+ if (currentPackAlignment != 4) {
+ gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
+ }
+
+ DataSourceSurface::ScopedMap map(surf, DataSourceSurface::READ);
+ gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA,
+ LOCAL_GL_UNSIGNED_BYTE, map.GetData());
+
+ if (currentPackAlignment != 4) {
+ gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, currentPackAlignment);
+ }
+
+ if (aFormat == SurfaceFormat::R8G8B8A8 ||
+ aFormat == SurfaceFormat::R8G8B8X8) {
+ SwapRAndBComponents(surf);
+ }
+
+ if (aYInvert) {
+ surf = YInvertImageSurface(surf, map.GetStride());
+ }
+
+ return surf.forget();
+}
+
+#define CLEANUP_IF_GLERROR_OCCURRED(x) \
+ if (DidGLErrorOccur(x)) { \
+ return false; \
+ }
+
+already_AddRefed<DataSourceSurface> GLReadTexImageHelper::ReadTexImage(
+ GLuint aTextureId, GLenum aTextureTarget, const gfx::IntSize& aSize,
+ /* ShaderConfigOGL.mFeature */ int aConfig, bool aYInvert) {
+ /* Allocate resulting image surface */
+ int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
+ RefPtr<DataSourceSurface> isurf = Factory::CreateDataSourceSurfaceWithStride(
+ aSize, SurfaceFormat::R8G8B8A8, stride);
+ if (NS_WARN_IF(!isurf)) {
+ return nullptr;
+ }
+
+ if (!ReadTexImage(isurf, aTextureId, aTextureTarget, aSize, aConfig,
+ aYInvert)) {
+ return nullptr;
+ }
+
+ return isurf.forget();
+}
+
+bool GLReadTexImageHelper::ReadTexImage(
+ DataSourceSurface* aDest, GLuint aTextureId, GLenum aTextureTarget,
+ const gfx::IntSize& aSize,
+ /* ShaderConfigOGL.mFeature */ int aConfig, bool aYInvert) {
+ MOZ_ASSERT(aTextureTarget == LOCAL_GL_TEXTURE_2D ||
+ aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL ||
+ aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+
+ mGL->MakeCurrent();
+
+ GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
+ GLuint rb, fb;
+
+ do {
+ mGL->fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
+ mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
+ mGL->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
+ mGL->fGetIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
+ mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
+ switch (aTextureTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex);
+ break;
+ case LOCAL_GL_TEXTURE_EXTERNAL:
+ mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldTex);
+ break;
+ case LOCAL_GL_TEXTURE_RECTANGLE:
+ mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_RECTANGLE, &oldTex);
+ break;
+ default: /* Already checked above */
+ break;
+ }
+
+ ScopedGLState scopedScissorTestState(mGL, LOCAL_GL_SCISSOR_TEST, false);
+ ScopedGLState scopedBlendState(mGL, LOCAL_GL_BLEND, false);
+ ScopedViewportRect scopedViewportRect(mGL, 0, 0, aSize.width, aSize.height);
+
+ /* Setup renderbuffer */
+ mGL->fGenRenderbuffers(1, &rb);
+ mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, rb);
+
+ GLenum rbInternalFormat =
+ mGL->IsGLES() ? (mGL->IsExtensionSupported(GLContext::OES_rgb8_rgba8)
+ ? LOCAL_GL_RGBA8
+ : LOCAL_GL_RGBA4)
+ : LOCAL_GL_RGBA;
+ mGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, rbInternalFormat,
+ aSize.width, aSize.height);
+ CLEANUP_IF_GLERROR_OCCURRED("when binding and creating renderbuffer");
+
+ /* Setup framebuffer */
+ mGL->fGenFramebuffers(1, &fb);
+ mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
+ mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+ LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_RENDERBUFFER, rb);
+ CLEANUP_IF_GLERROR_OCCURRED("when binding and creating framebuffer");
+
+ MOZ_ASSERT(mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) ==
+ LOCAL_GL_FRAMEBUFFER_COMPLETE);
+
+ /* Setup vertex and fragment shader */
+ GLuint program = TextureImageProgramFor(aTextureTarget, aConfig);
+ MOZ_ASSERT(program);
+
+ mGL->fUseProgram(program);
+ CLEANUP_IF_GLERROR_OCCURRED("when using program");
+ mGL->fUniform1i(mGL->fGetUniformLocation(program, "uTexture"), 0);
+ CLEANUP_IF_GLERROR_OCCURRED("when setting uniform location");
+
+ /* Setup quad geometry */
+ mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
+
+ float w = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE)
+ ? (float)aSize.width
+ : 1.0f;
+ float h = (aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE)
+ ? (float)aSize.height
+ : 1.0f;
+
+ const float vertexArray[4 * 2] = {-1.0f, -1.0f, 1.0f, -1.0f,
+ -1.0f, 1.0f, 1.0f, 1.0f};
+ ScopedVertexAttribPointer autoAttrib0(mGL, 0, 2, LOCAL_GL_FLOAT,
+ LOCAL_GL_FALSE, 0, 0, vertexArray);
+
+ const float u0 = 0.0f;
+ const float u1 = w;
+ const float v0 = aYInvert ? h : 0.0f;
+ const float v1 = aYInvert ? 0.0f : h;
+ const float texCoordArray[8] = {u0, v0, u1, v0, u0, v1, u1, v1};
+ ScopedVertexAttribPointer autoAttrib1(mGL, 1, 2, LOCAL_GL_FLOAT,
+ LOCAL_GL_FALSE, 0, 0, texCoordArray);
+
+ /* Bind the texture */
+ if (aTextureId) {
+ mGL->fBindTexture(aTextureTarget, aTextureId);
+ CLEANUP_IF_GLERROR_OCCURRED("when binding texture");
+ }
+
+ mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
+ CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
+
+ /* Read-back draw results */
+ ReadPixelsIntoDataSurface(mGL, aDest);
+ CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
+ } while (false);
+
+ /* Restore GL state */
+ mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
+ mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
+ mGL->fUseProgram(oldprog);
+
+ // note that deleting 0 has no effect in any of these calls
+ mGL->fDeleteRenderbuffers(1, &rb);
+ mGL->fDeleteFramebuffers(1, &fb);
+
+ if (aTextureId) mGL->fBindTexture(aTextureTarget, oldTex);
+
+ if (oldTexUnit != LOCAL_GL_TEXTURE0) mGL->fActiveTexture(oldTexUnit);
+
+ return true;
+}
+
+#undef CLEANUP_IF_GLERROR_OCCURRED
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLReadTexImageHelper.h b/gfx/gl/GLReadTexImageHelper.h
new file mode 100644
index 0000000000..c5b631fc1a
--- /dev/null
+++ b/gfx/gl/GLReadTexImageHelper.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLREADTEXIMAGEHELPER_H_
+#define GLREADTEXIMAGEHELPER_H_
+
+#include "GLContextTypes.h"
+#include "mozilla/Attributes.h"
+#include "nsSize.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/gfx/Types.h"
+
+namespace mozilla {
+
+namespace gfx {
+class DataSourceSurface;
+} // namespace gfx
+
+namespace gl {
+
+// Returns true if the `dest{Format,Type}` are the same as the
+// `read{Format,Type}`.
+bool GetActualReadFormats(GLContext* gl, GLenum destFormat, GLenum destType,
+ GLenum* out_readFormat, GLenum* out_readType);
+
+void ReadPixelsIntoBuffer(GLContext* gl, uint8_t* aData, int32_t aStride,
+ const gfx::IntSize& aSize,
+ gfx::SurfaceFormat aFormat);
+
+void ReadPixelsIntoDataSurface(GLContext* aGL,
+ gfx::DataSourceSurface* aSurface);
+
+already_AddRefed<gfx::DataSourceSurface> ReadBackSurface(
+ GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
+
+already_AddRefed<gfx::DataSourceSurface> YInvertImageSurface(
+ gfx::DataSourceSurface* aSurf, uint32_t aStride);
+
+void SwapRAndBComponents(gfx::DataSourceSurface* surf);
+
+class GLReadTexImageHelper final {
+ // The GLContext is the sole owner of the GLBlitHelper.
+ GLContext* mGL;
+
+ GLuint mPrograms[4];
+
+ GLuint TextureImageProgramFor(GLenum aTextureTarget, int aShader);
+
+ bool DidGLErrorOccur(const char* str);
+
+ public:
+ explicit GLReadTexImageHelper(GLContext* gl);
+ ~GLReadTexImageHelper();
+
+ /**
+ * Read the image data contained in aTexture, and return it as an
+ * ImageSurface. If GL_RGBA is given as the format, a
+ * SurfaceFormat::A8R8G8B8_UINT32 surface is returned. Not implemented yet: If
+ * GL_RGB is given as the format, a SurfaceFormat::X8R8G8B8_UINT32 surface is
+ * returned. If GL_LUMINANCE is given as the format, a SurfaceFormat::A8
+ * surface is returned.
+ *
+ * THIS IS EXPENSIVE. It is ridiculously expensive. Only do this
+ * if you absolutely positively must, and never in any performance
+ * critical path.
+ *
+ * NOTE: aShaderProgram is really mozilla::layers::ShaderProgramType. It is
+ * passed as int to eliminate including LayerManagerOGLProgram.h here.
+ */
+ already_AddRefed<gfx::DataSourceSurface> ReadTexImage(
+ GLuint aTextureId, GLenum aTextureTarget, const gfx::IntSize& aSize,
+ /* ShaderProgramType */ int aShaderProgram, bool aYInvert = false);
+
+ bool ReadTexImage(gfx::DataSourceSurface* aDest, GLuint aTextureId,
+ GLenum aTextureTarget, const gfx::IntSize& aSize,
+ int aShaderProgram, bool aYInvert = false);
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif
diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp
new file mode 100644
index 0000000000..9dda11b41a
--- /dev/null
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLScreenBuffer.h"
+
+#include "CompositorTypes.h"
+#include "GLContext.h"
+#include "gfx2DGlue.h"
+#include "MozFramebuffer.h"
+#include "SharedSurface.h"
+
+namespace mozilla::gl {
+
+// -
+// SwapChainPresenter
+
+// We need to apply pooling on Android because of the AndroidSurface slow
+// destructor bugs. They cause a noticeable performance hit. See bug
+// #1646073.
+static constexpr size_t kPoolSize =
+#if defined(MOZ_WIDGET_ANDROID)
+ 4;
+#else
+ 0;
+#endif
+
+UniquePtr<SwapChainPresenter> SwapChain::Acquire(
+ const gfx::IntSize& size, const gfx::ColorSpace2 colorSpace) {
+ MOZ_ASSERT(mFactory);
+
+ std::shared_ptr<SharedSurface> surf;
+ if (!mPool.empty()) {
+ // Try reuse
+ const auto& existingDesc = mPool.front()->mDesc;
+ auto newDesc = existingDesc;
+ newDesc.size = size;
+ newDesc.colorSpace = colorSpace;
+ if (newDesc != existingDesc || !mPool.front()->IsValid()) {
+ mPool = {};
+ }
+ }
+
+ // When mDestroyedCallback exists, recycling of SharedSurfaces is managed by
+ // the owner of the SwapChain by calling StoreRecycledSurface().
+ const auto poolSize = mDestroyedCallback ? 0 : kPoolSize;
+
+ if (!mPool.empty() && (!poolSize || mPool.size() == poolSize)) {
+ surf = mPool.front();
+ mPool.pop();
+ }
+ if (!surf) {
+ auto uniquePtrSurf = mFactory->CreateShared(size, colorSpace);
+ if (!uniquePtrSurf) return nullptr;
+ surf.reset(uniquePtrSurf.release());
+ }
+ mPool.push(surf);
+ while (mPool.size() > poolSize) {
+ mPool.pop();
+ }
+
+ auto ret = MakeUnique<SwapChainPresenter>(*this);
+ const auto old = ret->SwapBackBuffer(surf);
+ MOZ_ALWAYS_TRUE(!old);
+ return ret;
+}
+
+void SwapChain::ClearPool() {
+ mPool = {};
+ mPrevFrontBuffer = nullptr;
+}
+
+bool SwapChain::StoreRecycledSurface(
+ const std::shared_ptr<SharedSurface>& surf) {
+ MOZ_ASSERT(mFactory);
+ if (!mFactory || NS_WARN_IF(surf->mDesc.gl != mFactory->mDesc.gl)) {
+ // Ensure we don't accidentally store an expired shared surface or from a
+ // different context.
+ return false;
+ }
+ mPool.push(surf);
+ return true;
+}
+
+// -
+
+SwapChainPresenter::SwapChainPresenter(SwapChain& swapChain)
+ : mSwapChain(&swapChain) {
+ MOZ_RELEASE_ASSERT(mSwapChain->mPresenter == nullptr);
+ mSwapChain->mPresenter = this;
+}
+
+SwapChainPresenter::~SwapChainPresenter() {
+ if (!mSwapChain) return;
+ MOZ_RELEASE_ASSERT(mSwapChain->mPresenter == this);
+ mSwapChain->mPresenter = nullptr;
+
+ auto newFront = SwapBackBuffer(nullptr);
+ if (newFront) {
+ mSwapChain->mPrevFrontBuffer = mSwapChain->mFrontBuffer;
+ mSwapChain->mFrontBuffer = newFront;
+ }
+}
+
+std::shared_ptr<SharedSurface> SwapChainPresenter::SwapBackBuffer(
+ std::shared_ptr<SharedSurface> back) {
+ if (mBackBuffer) {
+ mBackBuffer->UnlockProd();
+ mBackBuffer->ProducerRelease();
+ mBackBuffer->Commit();
+ }
+ auto old = mBackBuffer;
+ mBackBuffer = back;
+ if (mBackBuffer) {
+ mBackBuffer->WaitForBufferOwnership();
+ mBackBuffer->ProducerAcquire();
+ mBackBuffer->LockProd();
+ }
+ return old;
+}
+
+GLuint SwapChainPresenter::Fb() const {
+ if (!mBackBuffer) return 0;
+ const auto& fb = mBackBuffer->mFb;
+ if (!fb) return 0;
+ return fb->mFB;
+}
+
+// -
+// SwapChain
+
+SwapChain::SwapChain() = default;
+
+SwapChain::~SwapChain() {
+ if (mPresenter) {
+ // Out of order destruction, but ok.
+ (void)mPresenter->SwapBackBuffer(nullptr);
+ mPresenter->mSwapChain = nullptr;
+ mPresenter = nullptr;
+ }
+ if (mDestroyedCallback) {
+ mDestroyedCallback();
+ }
+}
+
+} // namespace mozilla::gl
diff --git a/gfx/gl/GLScreenBuffer.h b/gfx/gl/GLScreenBuffer.h
new file mode 100644
index 0000000000..d281249771
--- /dev/null
+++ b/gfx/gl/GLScreenBuffer.h
@@ -0,0 +1,87 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* GLScreenBuffer is the abstraction for the "default framebuffer" used
+ * by an offscreen GLContext. Since it's only for offscreen GLContext's,
+ * it's only useful for things like WebGL, and is NOT used by the
+ * compositor's GLContext. Remember that GLContext provides an abstraction
+ * so that even if you want to draw to the 'screen', even if that's not
+ * actually the screen, just draw to 0. This GLScreenBuffer class takes the
+ * logic handling out of GLContext.
+ */
+
+#ifndef SCREEN_BUFFER_H_
+#define SCREEN_BUFFER_H_
+
+#include "GLTypes.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/UniquePtr.h"
+
+#include <functional>
+#include <queue>
+#include <memory>
+
+namespace mozilla {
+namespace gl {
+
+class SharedSurface;
+class SurfaceFactory;
+class SwapChain;
+
+class SwapChainPresenter final {
+ friend class SwapChain;
+
+ SwapChain* mSwapChain;
+ std::shared_ptr<SharedSurface> mBackBuffer;
+
+ public:
+ explicit SwapChainPresenter(SwapChain& swapChain);
+ ~SwapChainPresenter();
+
+ const auto& BackBuffer() const { return mBackBuffer; }
+
+ std::shared_ptr<SharedSurface> SwapBackBuffer(std::shared_ptr<SharedSurface>);
+ GLuint Fb() const;
+};
+
+// -
+
+class SwapChain final {
+ friend class SwapChainPresenter;
+
+ public:
+ UniquePtr<SurfaceFactory> mFactory;
+
+ private:
+ std::queue<std::shared_ptr<SharedSurface>> mPool;
+ std::shared_ptr<SharedSurface> mFrontBuffer;
+ std::function<void()> mDestroyedCallback;
+
+ public:
+ std::shared_ptr<SharedSurface>
+ mPrevFrontBuffer; // Hold this ref while it's in-flight.
+ private:
+ SwapChainPresenter* mPresenter = nullptr;
+
+ public:
+ SwapChain();
+ virtual ~SwapChain();
+
+ void ClearPool();
+ bool StoreRecycledSurface(const std::shared_ptr<SharedSurface>& surf);
+ const auto& FrontBuffer() const { return mFrontBuffer; }
+ UniquePtr<SwapChainPresenter> Acquire(const gfx::IntSize&, gfx::ColorSpace2);
+
+ void SetDestroyedCallback(std::function<void()>&& aDestroyedCallback) {
+ MOZ_ASSERT(!mDestroyedCallback);
+ mDestroyedCallback = std::move(aDestroyedCallback);
+ mPool = {};
+ }
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // SCREEN_BUFFER_H_
diff --git a/gfx/gl/GLTextureImage.cpp b/gfx/gl/GLTextureImage.cpp
new file mode 100644
index 0000000000..e2295753fc
--- /dev/null
+++ b/gfx/gl/GLTextureImage.cpp
@@ -0,0 +1,453 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLTextureImage.h"
+#include "GLContext.h"
+#include "gfxContext.h"
+#include "gfxPlatform.h"
+#include "gfxUtils.h"
+#include "gfx2DGlue.h"
+#include "mozilla/gfx/2D.h"
+#include "ScopedGLHelpers.h"
+#include "GLUploadHelpers.h"
+#include "GfxTexturesReporter.h"
+
+using namespace mozilla::gfx;
+
+namespace mozilla {
+namespace gl {
+
+already_AddRefed<TextureImage> CreateTextureImage(
+ GLContext* gl, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, GLenum aWrapMode,
+ TextureImage::Flags aFlags, TextureImage::ImageFormat aImageFormat) {
+ GLint maxTextureSize;
+ gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+ if (aSize.width > maxTextureSize || aSize.height > maxTextureSize) {
+ NS_ASSERTION(aWrapMode == LOCAL_GL_CLAMP_TO_EDGE,
+ "Can't support wrapping with tiles!");
+ return CreateTiledTextureImage(gl, aSize, aContentType, aFlags,
+ aImageFormat);
+ } else {
+ return CreateBasicTextureImage(gl, aSize, aContentType, aWrapMode, aFlags);
+ }
+}
+
+static already_AddRefed<TextureImage> TileGenFunc(
+ GLContext* gl, const IntSize& aSize, TextureImage::ContentType aContentType,
+ TextureImage::Flags aFlags, TextureImage::ImageFormat aImageFormat) {
+ return CreateBasicTextureImage(gl, aSize, aContentType,
+ LOCAL_GL_CLAMP_TO_EDGE, aFlags);
+}
+
+already_AddRefed<TextureImage> TextureImage::Create(
+ GLContext* gl, const gfx::IntSize& size,
+ TextureImage::ContentType contentType, GLenum wrapMode,
+ TextureImage::Flags flags) {
+ return CreateTextureImage(gl, size, contentType, wrapMode, flags);
+}
+
+bool TextureImage::UpdateFromDataSource(gfx::DataSourceSurface* aSurface,
+ const nsIntRegion* aDestRegion,
+ const gfx::IntPoint* aSrcOffset,
+ const gfx::IntPoint* aDstOffset) {
+ nsIntRegion destRegion = aDestRegion
+ ? *aDestRegion
+ : IntRect(0, 0, aSurface->GetSize().width,
+ aSurface->GetSize().height);
+ gfx::IntPoint srcPoint = aSrcOffset ? *aSrcOffset : gfx::IntPoint(0, 0);
+ gfx::IntPoint srcPointOut = aDstOffset ? *aDstOffset : gfx::IntPoint(0, 0);
+ return DirectUpdate(aSurface, destRegion, srcPoint, srcPointOut);
+}
+
+gfx::IntRect TextureImage::GetTileRect() {
+ return gfx::IntRect(gfx::IntPoint(0, 0), mSize);
+}
+
+gfx::IntRect TextureImage::GetSrcTileRect() { return GetTileRect(); }
+
+void TextureImage::UpdateUploadSize(size_t amount) {
+ if (mUploadSize > 0) {
+ GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryFreed,
+ mUploadSize);
+ }
+ mUploadSize = amount;
+ GfxTexturesReporter::UpdateAmount(GfxTexturesReporter::MemoryAllocated,
+ mUploadSize);
+}
+
+BasicTextureImage::~BasicTextureImage() {
+ GLContext* ctx = mGLContext;
+ if (ctx->IsDestroyed() || !ctx->IsValidOwningThread()) {
+ ctx = ctx->GetSharedContext();
+ }
+
+ // If we have a context, then we need to delete the texture;
+ // if we don't have a context (either real or shared),
+ // then they went away when the contex was deleted, because it
+ // was the only one that had access to it.
+ if (ctx && ctx->MakeCurrent()) {
+ ctx->fDeleteTextures(1, &mTexture);
+ }
+}
+
+void BasicTextureImage::BindTexture(GLenum aTextureUnit) {
+ mGLContext->fActiveTexture(aTextureUnit);
+ mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+ mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
+}
+
+bool BasicTextureImage::DirectUpdate(
+ gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion,
+ const gfx::IntPoint& aSrcOffset /* = gfx::IntPoint(0, 0) */,
+ const gfx::IntPoint& aDstOffset /* = gfx::IntPoint(0, 0) */) {
+ nsIntRegion region;
+ if (mTextureState == Valid) {
+ region = aRegion;
+ } else {
+ region = nsIntRegion(IntRect(0, 0, mSize.width, mSize.height));
+ }
+ bool needInit = mTextureState == Created;
+ size_t uploadSize;
+
+ mTextureFormat =
+ UploadSurfaceToTexture(mGLContext, aSurf, region, mTexture, mSize,
+ &uploadSize, needInit, aSrcOffset, aDstOffset);
+ if (mTextureFormat == SurfaceFormat::UNKNOWN) {
+ return false;
+ }
+
+ if (uploadSize > 0) {
+ UpdateUploadSize(uploadSize);
+ }
+ mTextureState = Valid;
+ return true;
+}
+
+void BasicTextureImage::Resize(const gfx::IntSize& aSize) {
+ mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+ // This matches the logic in UploadImageDataToTexture so that
+ // we avoid mixing formats.
+ GLenum format;
+ GLenum type;
+ if (mGLContext->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+ MOZ_ASSERT(!mGLContext->IsGLES());
+ format = LOCAL_GL_BGRA;
+ type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else {
+ format = LOCAL_GL_RGBA;
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ }
+
+ mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, aSize.width,
+ aSize.height, 0, format, type, nullptr);
+
+ mTextureState = Allocated;
+ mSize = aSize;
+}
+
+gfx::IntSize TextureImage::GetSize() const { return mSize; }
+
+TextureImage::TextureImage(const gfx::IntSize& aSize, GLenum aWrapMode,
+ ContentType aContentType, Flags aFlags)
+ : mSize(aSize),
+ mWrapMode(aWrapMode),
+ mContentType(aContentType),
+ mTextureFormat(gfx::SurfaceFormat::UNKNOWN),
+ mSamplingFilter(SamplingFilter::GOOD),
+ mFlags(aFlags),
+ mUploadSize(0) {}
+
+BasicTextureImage::BasicTextureImage(GLuint aTexture, const gfx::IntSize& aSize,
+ GLenum aWrapMode, ContentType aContentType,
+ GLContext* aContext,
+ TextureImage::Flags aFlags)
+ : TextureImage(aSize, aWrapMode, aContentType, aFlags),
+ mTexture(aTexture),
+ mTextureState(Created),
+ mGLContext(aContext) {}
+
+static bool WantsSmallTiles(GLContext* gl) {
+ // We can't use small tiles on the SGX 540, because of races in texture
+ // upload.
+ if (gl->WorkAroundDriverBugs() && gl->Renderer() == GLRenderer::SGX540)
+ return false;
+
+ // We should use small tiles for good performance if we can't use
+ // glTexSubImage2D() for some reason.
+ if (!ShouldUploadSubTextures(gl)) return true;
+
+ // Don't use small tiles otherwise. (If we implement incremental texture
+ // upload, then we will want to revisit this.)
+ return false;
+}
+
+TiledTextureImage::TiledTextureImage(GLContext* aGL, gfx::IntSize aSize,
+ TextureImage::ContentType aContentType,
+ TextureImage::Flags aFlags,
+ TextureImage::ImageFormat aImageFormat)
+ : TextureImage(aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, aFlags),
+ mCurrentImage(0),
+ mIterationCallback(nullptr),
+ mIterationCallbackData(nullptr),
+ mTileSize(0),
+ mRows(0),
+ mColumns(0),
+ mGL(aGL),
+ mTextureState(Created),
+ mImageFormat(aImageFormat) {
+ if (!(aFlags & TextureImage::DisallowBigImage) && WantsSmallTiles(mGL)) {
+ mTileSize = 256;
+ } else {
+ mGL->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, (GLint*)&mTileSize);
+ }
+ if (aSize.width != 0 && aSize.height != 0) {
+ Resize(aSize);
+ }
+}
+
+TiledTextureImage::~TiledTextureImage() = default;
+
+bool TiledTextureImage::DirectUpdate(
+ gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion,
+ const gfx::IntPoint& aSrcOffset /* = gfx::IntPoint(0, 0) */,
+ const gfx::IntPoint& aDstOffset /* = gfx::IntPoint(0, 0) */) {
+ // We don't handle non-zero aDstOffset
+ MOZ_RELEASE_ASSERT(aDstOffset == gfx::IntPoint());
+
+ if (mSize.width == 0 || mSize.height == 0) {
+ return true;
+ }
+
+ nsIntRegion region;
+
+ if (mTextureState != Valid) {
+ IntRect bounds = IntRect(0, 0, mSize.width, mSize.height);
+ region = nsIntRegion(bounds);
+ } else {
+ region = aRegion;
+ }
+
+ bool result = true;
+ int oldCurrentImage = mCurrentImage;
+ BeginBigImageIteration();
+ do {
+ IntRect tileRect = GetSrcTileRect();
+ int xPos = tileRect.X();
+ int yPos = tileRect.Y();
+
+ nsIntRegion tileRegion;
+ tileRegion.And(region, tileRect); // intersect with tile
+
+ if (tileRegion.IsEmpty()) continue;
+
+ tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
+
+ result &= mImages[mCurrentImage]->DirectUpdate(
+ aSurf, tileRegion, aSrcOffset + gfx::IntPoint(xPos, yPos));
+
+ if (mCurrentImage == mImages.Length() - 1) {
+ // We know we're done, but we still need to ensure that the callback
+ // gets called (e.g. to update the uploaded region).
+ NextTile();
+ break;
+ }
+ // Override a callback cancelling iteration if the texture wasn't valid.
+ // We need to force the update in that situation, or we may end up
+ // showing invalid/out-of-date texture data.
+ } while (NextTile() || (mTextureState != Valid));
+ mCurrentImage = oldCurrentImage;
+
+ mTextureFormat = mImages[0]->GetTextureFormat();
+ mTextureState = Valid;
+ return result;
+}
+
+void TiledTextureImage::BeginBigImageIteration() { mCurrentImage = 0; }
+
+bool TiledTextureImage::NextTile() {
+ bool continueIteration = true;
+
+ if (mIterationCallback)
+ continueIteration =
+ mIterationCallback(this, mCurrentImage, mIterationCallbackData);
+
+ if (mCurrentImage + 1 < mImages.Length()) {
+ mCurrentImage++;
+ return continueIteration;
+ }
+ return false;
+}
+
+void TiledTextureImage::SetIterationCallback(
+ BigImageIterationCallback aCallback, void* aCallbackData) {
+ mIterationCallback = aCallback;
+ mIterationCallbackData = aCallbackData;
+}
+
+gfx::IntRect TiledTextureImage::GetTileRect() {
+ if (!GetTileCount()) {
+ return gfx::IntRect();
+ }
+ gfx::IntRect rect = mImages[mCurrentImage]->GetTileRect();
+ unsigned int xPos = (mCurrentImage % mColumns) * mTileSize;
+ unsigned int yPos = (mCurrentImage / mColumns) * mTileSize;
+ rect.MoveBy(xPos, yPos);
+ return rect;
+}
+
+gfx::IntRect TiledTextureImage::GetSrcTileRect() {
+ gfx::IntRect rect = GetTileRect();
+ const bool needsYFlip = mFlags & OriginBottomLeft;
+ unsigned int srcY =
+ needsYFlip ? mSize.height - rect.Height() - rect.Y() : rect.Y();
+ return gfx::IntRect(rect.X(), srcY, rect.Width(), rect.Height());
+}
+
+void TiledTextureImage::BindTexture(GLenum aTextureUnit) {
+ if (!GetTileCount()) {
+ return;
+ }
+ mImages[mCurrentImage]->BindTexture(aTextureUnit);
+}
+
+/*
+ * Resize, trying to reuse tiles. The reuse strategy is to decide on reuse per
+ * column. A tile on a column is reused if it hasn't changed size, otherwise it
+ * is discarded/replaced. Extra tiles on a column are pruned after iterating
+ * each column, and extra rows are pruned after iteration over the entire image
+ * finishes.
+ */
+void TiledTextureImage::Resize(const gfx::IntSize& aSize) {
+ if (mSize == aSize && mTextureState != Created) {
+ return;
+ }
+
+ // calculate rows and columns, rounding up
+ unsigned int columns = (aSize.width + mTileSize - 1) / mTileSize;
+ unsigned int rows = (aSize.height + mTileSize - 1) / mTileSize;
+
+ // Iterate over old tile-store and insert/remove tiles as necessary
+ int row;
+ unsigned int i = 0;
+ for (row = 0; row < (int)rows; row++) {
+ // If we've gone beyond how many rows there were before, set mColumns to
+ // zero so that we only create new tiles.
+ if (row >= (int)mRows) mColumns = 0;
+
+ // Similarly, if we're on the last row of old tiles and the height has
+ // changed, discard all tiles in that row.
+ // This will cause the pruning of columns not to work, but we don't need
+ // to worry about that, as no more tiles will be reused past this point
+ // anyway.
+ if ((row == (int)mRows - 1) && (aSize.height != mSize.height)) mColumns = 0;
+
+ int col;
+ for (col = 0; col < (int)columns; col++) {
+ IntSize size( // use tilesize first, then the remainder
+ (col + 1) * mTileSize > (unsigned int)aSize.width
+ ? aSize.width % mTileSize
+ : mTileSize,
+ (row + 1) * mTileSize > (unsigned int)aSize.height
+ ? aSize.height % mTileSize
+ : mTileSize);
+
+ bool replace = false;
+
+ // Check if we can re-use old tiles.
+ if (col < (int)mColumns) {
+ // Reuse an existing tile. If the tile is an end-tile and the
+ // width differs, replace it instead.
+ if (mSize.width != aSize.width) {
+ if (col == (int)mColumns - 1) {
+ // Tile at the end of the old column, replace it with
+ // a new one.
+ replace = true;
+ } else if (col == (int)columns - 1) {
+ // Tile at the end of the new column, create a new one.
+ } else {
+ // Before the last column on both the old and new sizes,
+ // reuse existing tile.
+ i++;
+ continue;
+ }
+ } else {
+ // Width hasn't changed, reuse existing tile.
+ i++;
+ continue;
+ }
+ }
+
+ // Create a new tile.
+ RefPtr<TextureImage> teximg =
+ TileGenFunc(mGL, size, mContentType, mFlags, mImageFormat);
+ if (replace)
+ mImages.ReplaceElementAt(i, teximg);
+ else
+ mImages.InsertElementAt(i, teximg);
+ i++;
+ }
+
+ // Prune any unused tiles on the end of the column.
+ if (row < (int)mRows) {
+ for (col = (int)mColumns - col; col > 0; col--) {
+ mImages.RemoveElementAt(i);
+ }
+ }
+ }
+
+ // Prune any unused tiles at the end of the store.
+ mImages.RemoveLastElements(mImages.Length() - i);
+
+ // Reset tile-store properties.
+ mRows = rows;
+ mColumns = columns;
+ mSize = aSize;
+ mTextureState = Allocated;
+ mCurrentImage = 0;
+}
+
+uint32_t TiledTextureImage::GetTileCount() { return mImages.Length(); }
+
+already_AddRefed<TextureImage> CreateTiledTextureImage(
+ GLContext* aGL, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, TextureImage::Flags aFlags,
+ TextureImage::ImageFormat aImageFormat) {
+ RefPtr<TextureImage> texImage =
+ static_cast<TextureImage*>(new gl::TiledTextureImage(
+ aGL, aSize, aContentType, aFlags, aImageFormat));
+ return texImage.forget();
+}
+
+already_AddRefed<TextureImage> CreateBasicTextureImage(
+ GLContext* aGL, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, GLenum aWrapMode,
+ TextureImage::Flags aFlags) {
+ bool useNearestFilter = aFlags & TextureImage::UseNearestFilter;
+ if (!aGL->MakeCurrent()) {
+ return nullptr;
+ }
+
+ GLuint texture = 0;
+ aGL->fGenTextures(1, &texture);
+
+ ScopedBindTexture bind(aGL, texture);
+
+ GLint texfilter = useNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR;
+ aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
+ texfilter);
+ aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
+ texfilter);
+ aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, aWrapMode);
+ aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, aWrapMode);
+
+ RefPtr<BasicTextureImage> texImage = new BasicTextureImage(
+ texture, aSize, aWrapMode, aContentType, aGL, aFlags);
+ return texImage.forget();
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLTextureImage.h b/gfx/gl/GLTextureImage.h
new file mode 100644
index 0000000000..eb07b08832
--- /dev/null
+++ b/gfx/gl/GLTextureImage.h
@@ -0,0 +1,288 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLTEXTUREIMAGE_H_
+#define GLTEXTUREIMAGE_H_
+
+#include "nsRegion.h"
+#include "nsTArray.h"
+#include "gfxTypes.h"
+#include "GLContextTypes.h"
+#include "mozilla/gfx/Rect.h"
+#include "mozilla/RefPtr.h"
+
+class gfxASurface;
+
+namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+class DrawTarget;
+} // namespace gfx
+} // namespace mozilla
+
+namespace mozilla {
+namespace gl {
+class GLContext;
+
+/**
+ * A TextureImage provides a mechanism to synchronize data from a
+ * surface to a texture in the server. TextureImages are associated
+ * with one and only one GLContext.
+ */
+class TextureImage {
+ NS_INLINE_DECL_REFCOUNTING(TextureImage)
+ public:
+ enum TextureState {
+ Created, // Texture created, but has not had glTexImage called to
+ // initialize it.
+ Allocated, // Texture memory exists, but contents are invalid.
+ Valid // Texture fully ready to use.
+ };
+
+ enum Flags {
+ NoFlags = 0x0,
+ UseNearestFilter = 0x1,
+ OriginBottomLeft = 0x2,
+ DisallowBigImage = 0x4
+ };
+
+ typedef gfxContentType ContentType;
+ typedef gfxImageFormat ImageFormat;
+
+ static already_AddRefed<TextureImage> Create(
+ GLContext* gl, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, GLenum aWrapMode,
+ TextureImage::Flags aFlags = TextureImage::NoFlags);
+
+ /**
+ * The Image may contain several textures for different regions (tiles).
+ * These functions iterate over each sub texture image tile.
+ */
+ virtual void BeginBigImageIteration() {}
+
+ virtual bool NextTile() { return false; }
+
+ // Function prototype for a tile iteration callback. Returning false will
+ // cause iteration to be interrupted (i.e. the corresponding NextTile call
+ // will return false).
+ typedef bool (*BigImageIterationCallback)(TextureImage* aImage,
+ int aTileNumber,
+ void* aCallbackData);
+
+ // Sets a callback to be called every time NextTile is called.
+ virtual void SetIterationCallback(BigImageIterationCallback aCallback,
+ void* aCallbackData) {}
+
+ virtual gfx::IntRect GetTileRect();
+
+ virtual GLuint GetTextureID() = 0;
+
+ virtual uint32_t GetTileCount() { return 1; }
+
+ /**
+ * Set this TextureImage's size, and ensure a texture has been
+ * allocated.
+ * After a resize, the contents are undefined.
+ */
+ virtual void Resize(const gfx::IntSize& aSize) = 0;
+
+ /**
+ * Mark this texture as having valid contents. Call this after modifying
+ * the texture contents externally.
+ */
+ virtual void MarkValid() {}
+
+ /**
+ * aSurf - the source surface to update from
+ * aRegion - the region in this image to update
+ * aSrcOffset - offset in the source to update from
+ * aDstOffset - offset in the destination to update to
+ */
+ virtual bool DirectUpdate(
+ gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion,
+ const gfx::IntPoint& aSrcOffset = gfx::IntPoint(0, 0),
+ const gfx::IntPoint& aDstOffset = gfx::IntPoint(0, 0)) = 0;
+ bool UpdateFromDataSource(gfx::DataSourceSurface* aSurf,
+ const nsIntRegion* aDstRegion = nullptr,
+ const gfx::IntPoint* aSrcOffset = nullptr,
+ const gfx::IntPoint* aDstOffset = nullptr);
+
+ virtual void BindTexture(GLenum aTextureUnit) = 0;
+
+ /**
+ * Returns the image format of the texture. Only valid after
+ * DirectUpdate has been called.
+ */
+ virtual gfx::SurfaceFormat GetTextureFormat() { return mTextureFormat; }
+
+ /** Can be called safely at any time. */
+
+ /**
+ * If this TextureImage has a permanent gfxASurface backing,
+ * return it. Otherwise return nullptr.
+ */
+ virtual already_AddRefed<gfxASurface> GetBackingSurface() { return nullptr; }
+
+ gfx::IntSize GetSize() const;
+ ContentType GetContentType() const { return mContentType; }
+ GLenum GetWrapMode() const { return mWrapMode; }
+
+ void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter) {
+ mSamplingFilter = aSamplingFilter;
+ }
+
+ protected:
+ friend class GLContext;
+
+ void UpdateUploadSize(size_t amount);
+
+ /**
+ * After the ctor, the TextureImage is invalid. Implementations
+ * must allocate resources successfully before returning the new
+ * TextureImage from GLContext::CreateTextureImage(). That is,
+ * clients must not be given partially-constructed TextureImages.
+ */
+ TextureImage(const gfx::IntSize& aSize, GLenum aWrapMode,
+ ContentType aContentType, Flags aFlags = NoFlags);
+
+ // Protected destructor, to discourage deletion outside of Release():
+ virtual ~TextureImage() { UpdateUploadSize(0); }
+
+ virtual gfx::IntRect GetSrcTileRect();
+
+ gfx::IntSize mSize;
+ GLenum mWrapMode;
+ ContentType mContentType;
+ gfx::SurfaceFormat mTextureFormat;
+ gfx::SamplingFilter mSamplingFilter;
+ Flags mFlags;
+ size_t mUploadSize;
+};
+
+/**
+ * BasicTextureImage is the baseline TextureImage implementation ---
+ * it updates its texture by allocating a scratch buffer for the
+ * client to draw into, then using glTexSubImage2D() to upload the new
+ * pixels. Platforms must provide the code to create a new surface
+ * into which the updated pixels will be drawn, and the code to
+ * convert the update surface's pixels into an image on which we can
+ * glTexSubImage2D().
+ */
+class BasicTextureImage : public TextureImage {
+ public:
+ virtual ~BasicTextureImage();
+
+ BasicTextureImage(GLuint aTexture, const gfx::IntSize& aSize,
+ GLenum aWrapMode, ContentType aContentType,
+ GLContext* aContext,
+ TextureImage::Flags aFlags = TextureImage::NoFlags);
+
+ void BindTexture(GLenum aTextureUnit) override;
+
+ bool DirectUpdate(
+ gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion,
+ const gfx::IntPoint& aSrcOffset = gfx::IntPoint(0, 0),
+ const gfx::IntPoint& aDstOffset = gfx::IntPoint(0, 0)) override;
+ GLuint GetTextureID() override { return mTexture; }
+
+ void MarkValid() override { mTextureState = Valid; }
+
+ void Resize(const gfx::IntSize& aSize) override;
+
+ protected:
+ GLuint mTexture;
+ TextureState mTextureState;
+ RefPtr<GLContext> mGLContext;
+};
+
+/**
+ * A container class that complements many sub TextureImages into a big
+ * TextureImage. Aims to behave just like the real thing.
+ */
+
+class TiledTextureImage final : public TextureImage {
+ public:
+ TiledTextureImage(
+ GLContext* aGL, gfx::IntSize aSize, TextureImage::ContentType,
+ TextureImage::Flags aFlags = TextureImage::NoFlags,
+ TextureImage::ImageFormat aImageFormat = gfx::SurfaceFormat::UNKNOWN);
+ virtual ~TiledTextureImage();
+ void DumpDiv();
+ void Resize(const gfx::IntSize& aSize) override;
+ uint32_t GetTileCount() override;
+ void BeginBigImageIteration() override;
+ bool NextTile() override;
+ void SetIterationCallback(BigImageIterationCallback aCallback,
+ void* aCallbackData) override;
+ gfx::IntRect GetTileRect() override;
+ GLuint GetTextureID() override {
+ return mImages[mCurrentImage]->GetTextureID();
+ }
+ bool DirectUpdate(
+ gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion,
+ const gfx::IntPoint& aSrcOffset = gfx::IntPoint(0, 0),
+ const gfx::IntPoint& aDstOffset = gfx::IntPoint(0, 0)) override;
+ void BindTexture(GLenum) override;
+
+ protected:
+ gfx::IntRect GetSrcTileRect() override;
+
+ unsigned int mCurrentImage;
+ BigImageIterationCallback mIterationCallback;
+ void* mIterationCallbackData;
+ nsTArray<RefPtr<TextureImage> > mImages;
+ unsigned int mTileSize;
+ unsigned int mRows, mColumns;
+ GLContext* mGL;
+ TextureState mTextureState;
+ TextureImage::ImageFormat mImageFormat;
+};
+
+/**
+ * Creates a TextureImage of the basic implementation, can be useful in cases
+ * where we know we don't want to use platform-specific TextureImage.
+ * In doubt, use GLContext::CreateTextureImage instead.
+ */
+already_AddRefed<TextureImage> CreateBasicTextureImage(
+ GLContext* aGL, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, GLenum aWrapMode,
+ TextureImage::Flags aFlags);
+
+/**
+ * Creates a TiledTextureImage backed by platform-specific or basic
+ * TextureImages. In doubt, use GLContext::CreateTextureImage instead.
+ */
+already_AddRefed<TextureImage> CreateTiledTextureImage(
+ GLContext* aGL, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, TextureImage::Flags aFlags,
+ TextureImage::ImageFormat aImageFormat);
+
+/**
+ * Return a valid, allocated TextureImage of |aSize| with
+ * |aContentType|. If |aContentType| is COLOR, |aImageFormat| can be used
+ * to hint at the preferred RGB format, however it is not necessarily
+ * respected. The TextureImage's texture is configured to use
+ * |aWrapMode| (usually GL_CLAMP_TO_EDGE or GL_REPEAT) and by
+ * default, GL_LINEAR filtering. Specify
+ * |aFlags=UseNearestFilter| for GL_NEAREST filtering. Specify
+ * |aFlags=OriginBottomLeft| if the image is origin-bottom-left, instead of the
+ * default origin-top-left. Return
+ * nullptr if creating the TextureImage fails.
+ *
+ * The returned TextureImage may only be used with this GLContext.
+ * Attempting to use the returned TextureImage after this
+ * GLContext is destroyed will result in undefined (and likely
+ * crashy) behavior.
+ */
+already_AddRefed<TextureImage> CreateTextureImage(
+ GLContext* gl, const gfx::IntSize& aSize,
+ TextureImage::ContentType aContentType, GLenum aWrapMode,
+ TextureImage::Flags aFlags = TextureImage::NoFlags,
+ TextureImage::ImageFormat aImageFormat = gfx::SurfaceFormat::UNKNOWN);
+
+} // namespace gl
+} // namespace mozilla
+
+#endif /* GLTEXTUREIMAGE_H_ */
diff --git a/gfx/gl/GLTypes.h b/gfx/gl/GLTypes.h
new file mode 100644
index 0000000000..f5b317b4b7
--- /dev/null
+++ b/gfx/gl/GLTypes.h
@@ -0,0 +1,115 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLTYPES_H_
+#define GLTYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifndef GLAPIENTRY
+# ifdef WIN32
+# include <windef.h>
+# define GLAPIENTRY APIENTRY
+# define GLAPI
+# else
+# define GLAPIENTRY
+# define GLAPI
+# endif
+#endif
+
+typedef uint8_t realGLboolean;
+
+#if !defined(__gltypes_h_) && !defined(__gl_h_)
+# define __gltypes_h_
+# define __gl_h_
+
+typedef uint32_t GLenum;
+typedef uint32_t GLbitfield;
+typedef uint32_t GLuint;
+typedef int32_t GLint;
+typedef int32_t GLsizei;
+typedef int8_t GLbyte;
+typedef int16_t GLshort;
+typedef uint8_t GLubyte;
+typedef uint16_t GLushort;
+typedef float GLfloat;
+typedef float GLclampf;
+# ifndef GLdouble_defined
+typedef double GLdouble;
+# endif
+typedef double GLclampd;
+typedef void GLvoid;
+
+typedef char GLchar;
+# ifndef __gl2_h_
+# ifdef _WIN64
+typedef signed long long int GLintptr;
+typedef signed long long int GLsizeiptr;
+# else
+typedef signed long int GLintptr;
+typedef signed long int GLsizeiptr;
+# endif
+# endif
+
+#endif /* #if !defined(__gltypes_h_) && !defined(__gl_h_) */
+
+#include <stdint.h>
+
+// ARB_sync
+typedef struct __GLsync* GLsync;
+typedef int64_t GLint64;
+typedef uint64_t GLuint64;
+
+// OES_EGL_image (GLES)
+typedef void* GLeglImage;
+
+// KHR_debug
+typedef void(GLAPIENTRY* GLDEBUGPROC)(GLenum source, GLenum type, GLuint id,
+ GLenum severity, GLsizei length,
+ const GLchar* message,
+ const GLvoid* userParam);
+
+// EGL types
+typedef void* EGLImage;
+typedef int EGLint;
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef intptr_t EGLAttrib;
+typedef void* EGLConfig;
+typedef void* EGLContext;
+typedef void* EGLDisplay;
+typedef void* EGLDeviceEXT;
+typedef void* EGLSurface;
+typedef void* EGLClientBuffer;
+typedef void* EGLCastToRelevantPtr;
+typedef void* EGLImage;
+typedef void* EGLSync;
+typedef void* EGLStreamKHR;
+typedef uint64_t EGLTime;
+
+#define EGL_NO_CONTEXT ((EGLContext)0)
+#define EGL_NO_DISPLAY ((EGLDisplay)0)
+#define EGL_NO_SURFACE ((EGLSurface)0)
+#define EGL_NO_CONFIG ((EGLConfig) nullptr)
+#define EGL_NO_SYNC ((EGLSync)0)
+#define EGL_NO_IMAGE ((EGLImage)0)
+
+#ifdef XP_WIN
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN 1
+# endif
+
+# include <windef.h>
+
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+#else
+typedef void* EGLNativeDisplayType;
+typedef void* EGLNativePixmapType;
+typedef void* EGLNativeWindowType;
+#endif
+
+#endif // GLTYPES_H_
diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp
new file mode 100644
index 0000000000..c6efcfd656
--- /dev/null
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -0,0 +1,518 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLUploadHelpers.h"
+
+#include "GLContext.h"
+#include "mozilla/gfx/2D.h"
+#include "gfxUtils.h"
+#include "mozilla/gfx/Tools.h" // For BytesPerPixel
+#include "nsRegion.h"
+#include "GfxTexturesReporter.h"
+#include "mozilla/gfx/Logging.h"
+
+namespace mozilla {
+
+using namespace gfx;
+
+namespace gl {
+
+static unsigned int DataOffset(const IntPoint& aPoint, int32_t aStride,
+ SurfaceFormat aFormat) {
+ unsigned int data = aPoint.y * aStride;
+ data += aPoint.x * BytesPerPixel(aFormat);
+ return data;
+}
+
+static bool CheckUploadBounds(const IntSize& aDst, const IntSize& aSrc,
+ const IntPoint& aOffset) {
+ if (aOffset.x < 0 || aOffset.y < 0 || aOffset.x >= aSrc.width ||
+ aOffset.y >= aSrc.height) {
+ MOZ_ASSERT_UNREACHABLE("Offset outside source bounds");
+ return false;
+ }
+ if (aDst.width > (aSrc.width - aOffset.x) ||
+ aDst.height > (aSrc.height - aOffset.y)) {
+ MOZ_ASSERT_UNREACHABLE("Source has insufficient data");
+ return false;
+ }
+ return true;
+}
+
+static GLint GetAddressAlignment(ptrdiff_t aAddress) {
+ if (!(aAddress & 0x7)) {
+ return 8;
+ } else if (!(aAddress & 0x3)) {
+ return 4;
+ } else if (!(aAddress & 0x1)) {
+ return 2;
+ } else {
+ return 1;
+ }
+}
+
+// Take texture data in a given buffer and copy it into a larger buffer,
+// padding out the edge pixels for filtering if necessary
+static void CopyAndPadTextureData(const GLvoid* srcBuffer, GLvoid* dstBuffer,
+ GLsizei srcWidth, GLsizei srcHeight,
+ GLsizei dstWidth, GLsizei dstHeight,
+ GLsizei stride, GLint pixelsize) {
+ unsigned char* rowDest = static_cast<unsigned char*>(dstBuffer);
+ const unsigned char* source = static_cast<const unsigned char*>(srcBuffer);
+
+ for (GLsizei h = 0; h < srcHeight; ++h) {
+ memcpy(rowDest, source, srcWidth * pixelsize);
+ rowDest += dstWidth * pixelsize;
+ source += stride;
+ }
+
+ GLsizei padHeight = srcHeight;
+
+ // Pad out an extra row of pixels so that edge filtering doesn't use garbage
+ // data
+ if (dstHeight > srcHeight) {
+ memcpy(rowDest, source - stride, srcWidth * pixelsize);
+ padHeight++;
+ }
+
+ // Pad out an extra column of pixels
+ if (dstWidth > srcWidth) {
+ rowDest = static_cast<unsigned char*>(dstBuffer) + srcWidth * pixelsize;
+ for (GLsizei h = 0; h < padHeight; ++h) {
+ memcpy(rowDest, rowDest - pixelsize, pixelsize);
+ rowDest += dstWidth * pixelsize;
+ }
+ }
+}
+
+// In both of these cases (for the Adreno at least) it is impossible
+// to determine good or bad driver versions for POT texture uploads,
+// so blacklist them all. Newer drivers use a different rendering
+// string in the form "Adreno (TM) 200" and the drivers we've seen so
+// far work fine with NPOT textures, so don't blacklist those until we
+// have evidence of any problems with them.
+bool ShouldUploadSubTextures(GLContext* gl) {
+ if (!gl->WorkAroundDriverBugs()) return true;
+
+ // There are certain GPUs that we don't want to use glTexSubImage2D on
+ // because that function can be very slow and/or buggy
+ if (gl->Renderer() == GLRenderer::Adreno200 ||
+ gl->Renderer() == GLRenderer::Adreno205) {
+ return false;
+ }
+
+ // On PowerVR glTexSubImage does a readback, so it will be slower
+ // than just doing a glTexImage2D() directly. i.e. 26ms vs 10ms
+ if (gl->Renderer() == GLRenderer::SGX540 ||
+ gl->Renderer() == GLRenderer::SGX530) {
+ return false;
+ }
+
+ return true;
+}
+
+static void TexSubImage2DWithUnpackSubimageGLES(
+ GLContext* gl, GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLsizei stride, GLint pixelsize,
+ GLenum format, GLenum type, const GLvoid* pixels) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ // When using GL_UNPACK_ROW_LENGTH, we need to work around a Tegra
+ // driver crash where the driver apparently tries to read
+ // (stride - width * pixelsize) bytes past the end of the last input
+ // row. We only upload the first height-1 rows using GL_UNPACK_ROW_LENGTH,
+ // and then we upload the final row separately. See bug 697990.
+ int rowLength = stride / pixelsize;
+ if (gl->HasPBOState()) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
+ gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+ } else {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
+ gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height - 1,
+ format, type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+ gl->fTexSubImage2D(target, level, xoffset, yoffset + height - 1, width, 1,
+ format, type,
+ (const unsigned char*)pixels + (height - 1) * stride);
+ }
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+}
+
+static void TexSubImage2DWithoutUnpackSubimage(
+ GLContext* gl, GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLsizei stride, GLint pixelsize,
+ GLenum format, GLenum type, const GLvoid* pixels) {
+ // Not using the whole row of texture data and GL_UNPACK_ROW_LENGTH
+ // isn't supported. We make a copy of the texture data we're using,
+ // such that we're using the whole row of data in the copy. This turns
+ // out to be more efficient than uploading row-by-row; see bug 698197.
+
+ // Width and height are never more than 16384. At 16Ki*16Ki, 4bpp is 1GiB, but
+ // if we allow 8bpp (or higher) here, that's 2GiB, which would overflow on
+ // 32-bit.
+ MOZ_ASSERT(width <= 16384);
+ MOZ_ASSERT(height <= 16384);
+ MOZ_ASSERT(pixelsize < 8);
+
+ const auto size = CheckedInt<size_t>(width) * height * pixelsize;
+ if (!size.isValid()) {
+ // This should never happen, but we use a defensive check.
+ MOZ_ASSERT_UNREACHABLE("Unacceptable size calculated.!");
+ return;
+ }
+
+ unsigned char* newPixels = new (fallible) unsigned char[size.value()];
+
+ if (newPixels) {
+ unsigned char* rowDest = newPixels;
+ const unsigned char* rowSource = (const unsigned char*)pixels;
+ for (int h = 0; h < height; h++) {
+ memcpy(rowDest, rowSource, width * pixelsize);
+ rowDest += width * pixelsize;
+ rowSource += stride;
+ }
+
+ stride = width * pixelsize;
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)newPixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ type, newPixels);
+ delete[] newPixels;
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+
+ } else {
+ // If we did not have sufficient memory for the required
+ // temporary buffer, then fall back to uploading row-by-row.
+ const unsigned char* rowSource = (const unsigned char*)pixels;
+
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+
+ for (int i = 0; i < height; i++) {
+ gl->fTexSubImage2D(target, level, xoffset, yoffset + i, width, 1, format,
+ type, rowSource);
+ rowSource += stride;
+ }
+
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+ }
+}
+static void TexSubImage2DHelper(GLContext* gl, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLsizei width,
+ GLsizei height, GLsizei stride, GLint pixelsize,
+ GLenum format, GLenum type,
+ const GLvoid* pixels) {
+ if (gl->IsGLES()) {
+ if (stride == width * pixelsize) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+ } else if (gl->IsExtensionSupported(GLContext::EXT_unpack_subimage) ||
+ gl->HasPBOState()) {
+ TexSubImage2DWithUnpackSubimageGLES(gl, target, level, xoffset, yoffset,
+ width, height, stride, pixelsize,
+ format, type, pixels);
+
+ } else {
+ TexSubImage2DWithoutUnpackSubimage(gl, target, level, xoffset, yoffset,
+ width, height, stride, pixelsize,
+ format, type, pixels);
+ }
+ } else {
+ // desktop GL (non-ES) path
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ int rowLength = stride / pixelsize;
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
+ gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format,
+ type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+ }
+}
+
+static void TexImage2DHelper(GLContext* gl, GLenum target, GLint level,
+ GLint internalformat, GLsizei width,
+ GLsizei height, GLsizei stride, GLint pixelsize,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid* pixels) {
+ if (gl->IsGLES()) {
+ NS_ASSERTION(
+ format == (GLenum)internalformat,
+ "format and internalformat not the same for glTexImage2D on GLES2");
+
+ MOZ_ASSERT(width >= 0 && height >= 0);
+ if (!CanUploadNonPowerOfTwo(gl) &&
+ (stride != width * pixelsize || !IsPowerOfTwo((uint32_t)width) ||
+ !IsPowerOfTwo((uint32_t)height))) {
+ // Pad out texture width and height to the next power of two
+ // as we don't support/want non power of two texture uploads
+ GLsizei paddedWidth = RoundUpPow2((uint32_t)width);
+ GLsizei paddedHeight = RoundUpPow2((uint32_t)height);
+
+ // Width and height are never more than 16384. At 16Ki*16Ki, 4bpp is 1GiB,
+ // but if we allow 8bpp (or higher) here, that's 2GiB, which would
+ // overflow on 32-bit.
+ MOZ_ASSERT(width <= 16384);
+ MOZ_ASSERT(height <= 16384);
+ MOZ_ASSERT(pixelsize < 8);
+
+ const auto size =
+ CheckedInt<size_t>(paddedWidth) * paddedHeight * pixelsize;
+ if (!size.isValid()) {
+ // This should never happen, but we use a defensive check.
+ MOZ_ASSERT_UNREACHABLE("Unacceptable size calculated.!");
+ return;
+ }
+
+ GLvoid* paddedPixels = new unsigned char[size.value()];
+
+ // Pad out texture data to be in a POT sized buffer for uploading to
+ // a POT sized texture
+ CopyAndPadTextureData(pixels, paddedPixels, width, height, paddedWidth,
+ paddedHeight, stride, pixelsize);
+
+ gl->fPixelStorei(
+ LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)paddedPixels),
+ GetAddressAlignment((ptrdiff_t)paddedWidth * pixelsize)));
+ gl->fTexImage2D(target, border, internalformat, paddedWidth, paddedHeight,
+ border, format, type, paddedPixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+
+ delete[] static_cast<unsigned char*>(paddedPixels);
+ return;
+ }
+
+ if (stride == width * pixelsize) {
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ gl->fTexImage2D(target, border, internalformat, width, height, border,
+ format, type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+ } else {
+ // Use GLES-specific workarounds for GL_UNPACK_ROW_LENGTH; these are
+ // implemented in TexSubImage2D.
+ gl->fTexImage2D(target, border, internalformat, width, height, border,
+ format, type, nullptr);
+ TexSubImage2DHelper(gl, target, level, 0, 0, width, height, stride,
+ pixelsize, format, type, pixels);
+ }
+ } else {
+ // desktop GL (non-ES) path
+
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT,
+ std::min(GetAddressAlignment((ptrdiff_t)pixels),
+ GetAddressAlignment((ptrdiff_t)stride)));
+ int rowLength = stride / pixelsize;
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, rowLength);
+ gl->fTexImage2D(target, level, internalformat, width, height, border,
+ format, type, pixels);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, 0);
+ gl->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 4);
+ }
+}
+
+SurfaceFormat UploadImageDataToTexture(
+ GLContext* gl, unsigned char* aData, const gfx::IntSize& aDataSize,
+ const IntPoint& aDstOffset, int32_t aStride, SurfaceFormat aFormat,
+ const nsIntRegion& aDstRegion, GLuint aTexture, const gfx::IntSize& aSize,
+ size_t* aOutUploadSize, bool aNeedInit, GLenum aTextureUnit,
+ GLenum aTextureTarget) {
+ gl->MakeCurrent();
+ gl->fActiveTexture(aTextureUnit);
+ gl->fBindTexture(aTextureTarget, aTexture);
+
+ GLenum format = 0;
+ GLenum internalFormat = 0;
+ GLenum type = 0;
+ int32_t pixelSize = BytesPerPixel(aFormat);
+ SurfaceFormat surfaceFormat = gfx::SurfaceFormat::UNKNOWN;
+
+ MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
+ gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
+
+ switch (aFormat) {
+ case SurfaceFormat::B8G8R8A8:
+ if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+ format = LOCAL_GL_BGRA;
+ surfaceFormat = SurfaceFormat::R8G8B8A8;
+ type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else {
+ format = LOCAL_GL_RGBA;
+ surfaceFormat = SurfaceFormat::B8G8R8A8;
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ }
+ internalFormat = LOCAL_GL_RGBA;
+ break;
+ case SurfaceFormat::B8G8R8X8:
+ // Treat BGRX surfaces as BGRA except for the surface
+ // format used.
+ if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+ format = LOCAL_GL_BGRA;
+ surfaceFormat = SurfaceFormat::R8G8B8X8;
+ type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ } else {
+ format = LOCAL_GL_RGBA;
+ surfaceFormat = SurfaceFormat::B8G8R8X8;
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ }
+ internalFormat = LOCAL_GL_RGBA;
+ break;
+ case SurfaceFormat::R8G8B8A8:
+ if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+ // Upload our RGBA as BGRA, but store that the uploaded format is
+ // BGRA. (sample from R to get B)
+ format = LOCAL_GL_BGRA;
+ type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ surfaceFormat = SurfaceFormat::B8G8R8A8;
+ } else {
+ format = LOCAL_GL_RGBA;
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ surfaceFormat = SurfaceFormat::R8G8B8A8;
+ }
+ internalFormat = LOCAL_GL_RGBA;
+ break;
+ case SurfaceFormat::R8G8B8X8:
+ // Treat RGBX surfaces as RGBA except for the surface
+ // format used.
+ if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
+ format = LOCAL_GL_BGRA;
+ type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
+ surfaceFormat = SurfaceFormat::B8G8R8X8;
+ } else {
+ format = LOCAL_GL_RGBA;
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ surfaceFormat = SurfaceFormat::R8G8B8X8;
+ }
+ internalFormat = LOCAL_GL_RGBA;
+ break;
+ case SurfaceFormat::R5G6B5_UINT16:
+ internalFormat = format = LOCAL_GL_RGB;
+ type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
+ surfaceFormat = SurfaceFormat::R5G6B5_UINT16;
+ break;
+ case SurfaceFormat::A8:
+ if (gl->IsGLES()) {
+ format = LOCAL_GL_LUMINANCE;
+ internalFormat = LOCAL_GL_LUMINANCE;
+ } else {
+ format = LOCAL_GL_RED;
+ internalFormat = LOCAL_GL_R8;
+ }
+ type = LOCAL_GL_UNSIGNED_BYTE;
+ // We don't have a specific luminance shader
+ surfaceFormat = SurfaceFormat::A8;
+ break;
+ case SurfaceFormat::A16:
+ if (gl->IsGLES()) {
+ format = LOCAL_GL_LUMINANCE;
+ internalFormat = LOCAL_GL_LUMINANCE16;
+ } else {
+ format = LOCAL_GL_RED;
+ internalFormat = LOCAL_GL_R16;
+ }
+ type = LOCAL_GL_UNSIGNED_SHORT;
+ // We don't have a specific luminance shader
+ surfaceFormat = SurfaceFormat::A8;
+ pixelSize = 2;
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unhandled image surface format!");
+ }
+
+ if (aOutUploadSize) {
+ *aOutUploadSize = 0;
+ }
+
+ if (surfaceFormat == gfx::SurfaceFormat::UNKNOWN) {
+ return gfx::SurfaceFormat::UNKNOWN;
+ }
+
+ // We can only skip SubTextures if aOffset = 0 because we need the whole
+ // buffer
+ if (aNeedInit || (!ShouldUploadSubTextures(gl) && aDstOffset == IntPoint())) {
+ if (!CheckUploadBounds(aSize, aDataSize, IntPoint())) {
+ return SurfaceFormat::UNKNOWN;
+ }
+ // If the texture needs initialized, or we are unable to
+ // upload sub textures, then initialize and upload the entire
+ // texture.
+ TexImage2DHelper(gl, aTextureTarget, 0, internalFormat, aSize.width,
+ aSize.height, aStride, pixelSize, 0, format, type, aData);
+
+ if (aOutUploadSize && aNeedInit) {
+ uint32_t texelSize = GetBytesPerTexel(internalFormat, type);
+ size_t numTexels = size_t(aSize.width) * size_t(aSize.height);
+ *aOutUploadSize += texelSize * numTexels;
+ }
+ } else {
+ // Upload each rect in the region to the texture
+ for (auto iter = aDstRegion.RectIter(); !iter.Done(); iter.Next()) {
+ IntRect rect = iter.Get();
+ if (!CheckUploadBounds(rect.Size(), aDataSize, rect.TopLeft())) {
+ return SurfaceFormat::UNKNOWN;
+ }
+
+ const unsigned char* rectData =
+ aData + DataOffset(rect.TopLeft(), aStride, aFormat);
+
+ rect += aDstOffset;
+ TexSubImage2DHelper(gl, aTextureTarget, 0, rect.X(), rect.Y(),
+ rect.Width(), rect.Height(), aStride, pixelSize,
+ format, type, rectData);
+ }
+ }
+
+ return surfaceFormat;
+}
+
+SurfaceFormat UploadSurfaceToTexture(GLContext* gl, DataSourceSurface* aSurface,
+ const nsIntRegion& aDstRegion,
+ GLuint aTexture, const gfx::IntSize& aSize,
+ size_t* aOutUploadSize, bool aNeedInit,
+ const gfx::IntPoint& aSrcOffset,
+ const gfx::IntPoint& aDstOffset,
+ GLenum aTextureUnit,
+ GLenum aTextureTarget) {
+ DataSourceSurface::ScopedMap map(aSurface, DataSourceSurface::READ);
+ int32_t stride = map.GetStride();
+ SurfaceFormat format = aSurface->GetFormat();
+ gfx::IntSize size = aSurface->GetSize();
+
+ // only fail if we'll need the entire surface for initialization
+ if (aNeedInit && !CheckUploadBounds(aSize, size, aSrcOffset)) {
+ return SurfaceFormat::UNKNOWN;
+ }
+
+ unsigned char* data = map.GetData() + DataOffset(aSrcOffset, stride, format);
+ size.width -= aSrcOffset.x;
+ size.height -= aSrcOffset.y;
+
+ return UploadImageDataToTexture(gl, data, size, aDstOffset, stride, format,
+ aDstRegion, aTexture, aSize, aOutUploadSize,
+ aNeedInit, aTextureUnit, aTextureTarget);
+}
+
+bool CanUploadNonPowerOfTwo(GLContext* gl) {
+ if (!gl->WorkAroundDriverBugs()) return true;
+
+ // Some GPUs driver crash when uploading non power of two 565 textures.
+ return gl->Renderer() != GLRenderer::Adreno200 &&
+ gl->Renderer() != GLRenderer::Adreno205;
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/GLUploadHelpers.h b/gfx/gl/GLUploadHelpers.h
new file mode 100644
index 0000000000..3bf071fd0b
--- /dev/null
+++ b/gfx/gl/GLUploadHelpers.h
@@ -0,0 +1,77 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GLUploadHelpers_h_
+#define GLUploadHelpers_h_
+
+#include "GLDefs.h"
+#include "mozilla/gfx/Types.h"
+#include "nsPoint.h"
+#include "nsRegionFwd.h"
+
+namespace mozilla {
+
+namespace gfx {
+class DataSourceSurface;
+} // namespace gfx
+
+namespace gl {
+
+class GLContext;
+
+/**
+ * Uploads image data to an OpenGL texture, initializing the texture
+ * first if necessary.
+ *
+ * \param gl The GL Context to use.
+ * \param aData Start of image data of surface to upload.
+ * Corresponds to the first pixel of the texture.
+ * \param aDataSize The image data's size.
+ * \param aStride The image data's stride.
+ * \param aFormat The image data's format.
+ * \param aDstRegion Region of the texture to upload.
+ * \param aTexture The OpenGL texture to use. Must refer to a valid texture.
+ * \param aSize The full size of the texture.
+ * \param aOutUploadSize If set, the number of bytes the texture requires will
+ * be returned here.
+ * \param aNeedInit Indicates whether a new texture must be allocated.
+ * \param aTextureUnit The texture unit used temporarily to upload the surface.
+ * This may be overridden, so clients should not rely on
+ * the aTexture being bound to aTextureUnit after this call,
+ * or even on aTextureUnit being active.
+ * \param aTextureTarget The texture target to use.
+ * \return Surface format of this texture.
+ */
+gfx::SurfaceFormat UploadImageDataToTexture(
+ GLContext* gl, unsigned char* aData, const gfx::IntSize& aDataSize,
+ const gfx::IntPoint& aDstOffset, int32_t aStride,
+ gfx::SurfaceFormat aFormat, const nsIntRegion& aDstRegion, GLuint aTexture,
+ const gfx::IntSize& aSize, size_t* aOutUploadSize = nullptr,
+ bool aNeedInit = false, GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
+ GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
+
+/**
+ * Convenience wrapper around UploadImageDataToTexture for
+ * gfx::DataSourceSurface's.
+ *
+ * \param aSurface The surface from which to upload image data.
+ * \param aSrcPoint Offset into aSurface where this texture's data begins.
+ */
+gfx::SurfaceFormat UploadSurfaceToTexture(
+ GLContext* gl, gfx::DataSourceSurface* aSurface,
+ const nsIntRegion& aDstRegion, GLuint aTexture, const gfx::IntSize& aSize,
+ size_t* aOutUploadSize = nullptr, bool aNeedInit = false,
+ const gfx::IntPoint& aSrcOffset = gfx::IntPoint(0, 0),
+ const gfx::IntPoint& aDstOffset = gfx::IntPoint(0, 0),
+ GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
+ GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
+
+bool ShouldUploadSubTextures(GLContext* gl);
+bool CanUploadNonPowerOfTwo(GLContext* gl);
+
+} // namespace gl
+} // namespace mozilla
+
+#endif
diff --git a/gfx/gl/GLXLibrary.h b/gfx/gl/GLXLibrary.h
new file mode 100644
index 0000000000..d2577c935c
--- /dev/null
+++ b/gfx/gl/GLXLibrary.h
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_GLXLIBRARY_H
+#define GFX_GLXLIBRARY_H
+
+#include "GLContext.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/DataMutex.h"
+#include "mozilla/gfx/XlibDisplay.h"
+#include "prlink.h"
+typedef realGLboolean GLboolean;
+
+// stuff from glx.h
+#include "X11/Xlib.h"
+#include "X11/Xutil.h" // for XVisualInfo
+#include "X11UndefineNone.h"
+typedef struct __GLXcontextRec* GLXContext;
+typedef XID GLXPixmap;
+typedef XID GLXDrawable;
+/* GLX 1.3 and later */
+typedef struct __GLXFBConfigRec* GLXFBConfig;
+// end of stuff from glx.h
+#include "prenv.h"
+
+struct PRLibrary;
+class gfxASurface;
+
+namespace mozilla {
+namespace gl {
+
+class GLContextGLX;
+
+class GLXLibrary final {
+ public:
+ bool EnsureInitialized(Display* aDisplay);
+
+ private:
+ class WrapperScope final {
+ const GLXLibrary& mGlx;
+ const char* const mFuncName;
+ Display* const mDisplay;
+
+ public:
+ WrapperScope(const GLXLibrary& glx, const char* const funcName,
+ Display* aDisplay);
+ ~WrapperScope();
+ };
+
+ public:
+#ifdef DEBUG
+# define DECL_WRAPPER_SCOPE(display) \
+ const WrapperScope wrapperScope(*this, __func__, display);
+#else
+# define DECL_WRAPPER_SCOPE(display)
+#endif
+
+ void fDestroyContext(Display* display, GLXContext context) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fDestroyContext(display, context);
+ }
+
+ Bool fMakeCurrent(Display* display, GLXDrawable drawable,
+ GLXContext context) const {
+ DECL_WRAPPER_SCOPE(display)
+ GLContext::ResetTLSCurrentContext();
+ return mSymbols.fMakeCurrent(display, drawable, context);
+ }
+
+ XVisualInfo* fGetConfig(Display* display, XVisualInfo* info, int attrib,
+ int* value) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fGetConfig(display, info, attrib, value);
+ }
+
+ GLXContext fGetCurrentContext() const {
+ DECL_WRAPPER_SCOPE(nullptr)
+ return mSymbols.fGetCurrentContext();
+ }
+
+ GLXFBConfig* fChooseFBConfig(Display* display, int screen,
+ const int* attrib_list, int* nelements) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fChooseFBConfig(display, screen, attrib_list, nelements);
+ }
+
+ XVisualInfo* fChooseVisual(Display* display, int screen,
+ int* attrib_list) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fChooseVisual(display, screen, attrib_list);
+ }
+
+ GLXFBConfig* fGetFBConfigs(Display* display, int screen,
+ int* nelements) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fGetFBConfigs(display, screen, nelements);
+ }
+
+ GLXContext fCreateNewContext(Display* display, GLXFBConfig config,
+ int render_type, GLXContext share_list,
+ Bool direct) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fCreateNewContext(display, config, render_type, share_list,
+ direct);
+ }
+
+ int fGetFBConfigAttrib(Display* display, GLXFBConfig config, int attribute,
+ int* value) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fGetFBConfigAttrib(display, config, attribute, value);
+ }
+
+ void fSwapBuffers(Display* display, GLXDrawable drawable) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fSwapBuffers(display, drawable);
+ }
+
+ const char* fQueryExtensionsString(Display* display, int screen) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fQueryExtensionsString(display, screen);
+ }
+
+ const char* fGetClientString(Display* display, int screen) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fGetClientString(display, screen);
+ }
+
+ const char* fQueryServerString(Display* display, int screen, int name) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fQueryServerString(display, screen, name);
+ }
+
+ GLXPixmap fCreatePixmap(Display* display, GLXFBConfig config, Pixmap pixmap,
+ const int* attrib_list) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fCreatePixmap(display, config, pixmap, attrib_list);
+ }
+
+ GLXPixmap fCreateGLXPixmapWithConfig(Display* display, GLXFBConfig config,
+ Pixmap pixmap) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fCreateGLXPixmapWithConfig(display, config, pixmap);
+ }
+
+ void fDestroyPixmap(Display* display, GLXPixmap pixmap) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fDestroyPixmap(display, pixmap);
+ }
+
+ Bool fQueryVersion(Display* display, int* major, int* minor) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fQueryVersion(display, major, minor);
+ }
+
+ void fBindTexImage(Display* display, GLXDrawable drawable, int buffer,
+ const int* attrib_list) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fBindTexImageEXT(display, drawable, buffer, attrib_list);
+ }
+
+ void fReleaseTexImage(Display* display, GLXDrawable drawable,
+ int buffer) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fReleaseTexImageEXT(display, drawable, buffer);
+ }
+
+ void fWaitGL() const {
+ DECL_WRAPPER_SCOPE(nullptr)
+ return mSymbols.fWaitGL();
+ }
+
+ void fWaitX() const {
+ DECL_WRAPPER_SCOPE(nullptr)
+ return mSymbols.fWaitX();
+ }
+
+ GLXContext fCreateContextAttribs(Display* display, GLXFBConfig config,
+ GLXContext share_list, Bool direct,
+ const int* attrib_list) const {
+ DECL_WRAPPER_SCOPE(display)
+ return mSymbols.fCreateContextAttribsARB(display, config, share_list,
+ direct, attrib_list);
+ }
+
+ int fGetVideoSync(unsigned int* count) const {
+ DECL_WRAPPER_SCOPE(nullptr)
+ return mSymbols.fGetVideoSyncSGI(count);
+ }
+
+ int fWaitVideoSync(int divisor, int remainder, unsigned int* count) const {
+ DECL_WRAPPER_SCOPE(nullptr)
+ return mSymbols.fWaitVideoSyncSGI(divisor, remainder, count);
+ }
+
+ void fSwapInterval(Display* dpy, GLXDrawable drawable, int interval) const {
+ DECL_WRAPPER_SCOPE(dpy)
+ return mSymbols.fSwapIntervalEXT(dpy, drawable, interval);
+ }
+
+ int fQueryDrawable(Display* dpy, GLXDrawable drawable, int attribute,
+ unsigned int* value) const {
+ DECL_WRAPPER_SCOPE(dpy)
+ return mSymbols.fQueryDrawable(dpy, drawable, attribute, value);
+ }
+#undef DECL_WRAPPER_SCOPE
+
+ ////
+
+ bool HasRobustness() { return mHasRobustness; }
+ bool HasVideoMemoryPurge() { return mHasVideoMemoryPurge; }
+ bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
+ bool SupportsTextureFromPixmap(gfxASurface* aSurface);
+ bool SupportsVideoSync(Display* aDisplay);
+ bool SupportsSwapControl() const { return bool(mSymbols.fSwapIntervalEXT); }
+ bool SupportsBufferAge() const {
+ MOZ_ASSERT(mInitialized);
+ return mHasBufferAge;
+ }
+ bool IsATI() { return mIsATI; }
+ bool IsMesa() { return mClientIsMesa; }
+
+ auto GetGetProcAddress() const { return mSymbols.fGetProcAddress; }
+
+ std::shared_ptr<gfx::XlibDisplay> GetDisplay();
+
+ private:
+ struct {
+ void(GLAPIENTRY* fDestroyContext)(Display*, GLXContext);
+ Bool(GLAPIENTRY* fMakeCurrent)(Display*, GLXDrawable, GLXContext);
+ XVisualInfo*(GLAPIENTRY* fGetConfig)(Display*, XVisualInfo*, int, int*);
+ GLXContext(GLAPIENTRY* fGetCurrentContext)();
+ void*(GLAPIENTRY* fGetProcAddress)(const char*);
+ GLXFBConfig*(GLAPIENTRY* fChooseFBConfig)(Display*, int, const int*, int*);
+ XVisualInfo*(GLAPIENTRY* fChooseVisual)(Display*, int, const int*);
+ GLXFBConfig*(GLAPIENTRY* fGetFBConfigs)(Display*, int, int*);
+ GLXContext(GLAPIENTRY* fCreateNewContext)(Display*, GLXFBConfig, int,
+ GLXContext, Bool);
+ int(GLAPIENTRY* fGetFBConfigAttrib)(Display*, GLXFBConfig, int, int*);
+ void(GLAPIENTRY* fSwapBuffers)(Display*, GLXDrawable);
+ const char*(GLAPIENTRY* fQueryExtensionsString)(Display*, int);
+ const char*(GLAPIENTRY* fGetClientString)(Display*, int);
+ const char*(GLAPIENTRY* fQueryServerString)(Display*, int, int);
+ GLXPixmap(GLAPIENTRY* fCreatePixmap)(Display*, GLXFBConfig, Pixmap,
+ const int*);
+ GLXPixmap(GLAPIENTRY* fCreateGLXPixmapWithConfig)(Display*, GLXFBConfig,
+ Pixmap);
+ void(GLAPIENTRY* fDestroyPixmap)(Display*, GLXPixmap);
+ Bool(GLAPIENTRY* fQueryVersion)(Display*, int*, int*);
+ void(GLAPIENTRY* fWaitGL)();
+ void(GLAPIENTRY* fWaitX)();
+ void(GLAPIENTRY* fBindTexImageEXT)(Display*, GLXDrawable, int, const int*);
+ void(GLAPIENTRY* fReleaseTexImageEXT)(Display*, GLXDrawable, int);
+ GLXContext(GLAPIENTRY* fCreateContextAttribsARB)(Display*, GLXFBConfig,
+ GLXContext, Bool,
+ const int*);
+ int(GLAPIENTRY* fGetVideoSyncSGI)(unsigned int*);
+ int(GLAPIENTRY* fWaitVideoSyncSGI)(int, int, unsigned int*);
+ void(GLAPIENTRY* fSwapIntervalEXT)(Display*, GLXDrawable, int);
+ int(GLAPIENTRY* fQueryDrawable)(Display*, GLXDrawable, int, unsigned int*);
+ } mSymbols = {};
+
+ bool mInitialized = false;
+ bool mTriedInitializing = false;
+ bool mDebug = false;
+ bool mHasRobustness = false;
+ bool mHasVideoMemoryPurge = false;
+ bool mHasCreateContextAttribs = false;
+ bool mHasVideoSync = false;
+ bool mHasBufferAge = false;
+ bool mIsATI = false;
+ bool mIsNVIDIA = false;
+ bool mClientIsMesa = false;
+ PRLibrary* mOGLLibrary = nullptr;
+ StaticDataMutex<std::weak_ptr<gfx::XlibDisplay>> mOwnDisplay{
+ "GLXLibrary::mOwnDisplay"};
+};
+
+// a global GLXLibrary instance
+extern GLXLibrary sGLXLibrary;
+
+} /* namespace gl */
+} /* namespace mozilla */
+#endif /* GFX_GLXLIBRARY_H */
diff --git a/gfx/gl/GfxTexturesReporter.cpp b/gfx/gl/GfxTexturesReporter.cpp
new file mode 100644
index 0000000000..bd169e0013
--- /dev/null
+++ b/gfx/gl/GfxTexturesReporter.cpp
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <string>
+#include <sstream>
+#include "nsExceptionHandler.h"
+#include "GfxTexturesReporter.h"
+#include "mozilla/StaticPrefs_gfx.h"
+
+using namespace mozilla::gl;
+
+NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter)
+
+mozilla::Atomic<size_t> GfxTexturesReporter::sAmount(0);
+mozilla::Atomic<size_t> GfxTexturesReporter::sPeakAmount(0);
+mozilla::Atomic<size_t> GfxTexturesReporter::sTileWasteAmount(0);
+
+static std::string FormatBytes(size_t amount) {
+ std::stringstream stream;
+ int depth = 0;
+ double val = amount;
+ while (val > 1024) {
+ val /= 1024;
+ depth++;
+ }
+
+ const char* unit;
+ switch (depth) {
+ case 0:
+ unit = "bytes";
+ break;
+ case 1:
+ unit = "KB";
+ break;
+ case 2:
+ unit = "MB";
+ break;
+ case 3:
+ unit = "GB";
+ break;
+ default:
+ unit = "";
+ break;
+ }
+
+ stream << val << " " << unit;
+ return stream.str();
+}
+
+/* static */
+void GfxTexturesReporter::UpdateAmount(MemoryUse action, size_t amount) {
+ if (action == MemoryFreed) {
+ MOZ_RELEASE_ASSERT(
+ amount <= sAmount,
+ "GFX: Current texture usage greater than update amount.");
+ sAmount -= amount;
+
+ if (StaticPrefs::gfx_logging_texture_usage_enabled_AtStartup()) {
+ printf_stderr("Current texture usage: %s\n",
+ FormatBytes(sAmount).c_str());
+ }
+ } else {
+ sAmount += amount;
+ if (sAmount > sPeakAmount) {
+ sPeakAmount.exchange(sAmount);
+ if (StaticPrefs::gfx_logging_peak_texture_usage_enabled_AtStartup()) {
+ printf_stderr("Peak texture usage: %s\n",
+ FormatBytes(sPeakAmount).c_str());
+ }
+ }
+ }
+
+ CrashReporter::AnnotateTexturesSize(sAmount);
+}
diff --git a/gfx/gl/GfxTexturesReporter.h b/gfx/gl/GfxTexturesReporter.h
new file mode 100644
index 0000000000..077fc0e879
--- /dev/null
+++ b/gfx/gl/GfxTexturesReporter.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFXTEXTURESREPORTER_H_
+#define GFXTEXTURESREPORTER_H_
+
+#include "mozilla/Atomics.h"
+#include "nsIMemoryReporter.h"
+#include "GLTypes.h"
+
+namespace mozilla {
+namespace gl {
+
+class GfxTexturesReporter final : public nsIMemoryReporter {
+ ~GfxTexturesReporter() = default;
+
+ public:
+ NS_DECL_ISUPPORTS
+
+ GfxTexturesReporter() {
+#ifdef DEBUG
+ // There must be only one instance of this class, due to |sAmount|
+ // being static. Assert this.
+ static bool hasRun = false;
+ MOZ_ASSERT(!hasRun);
+ hasRun = true;
+#endif
+ }
+
+ enum MemoryUse {
+ // when memory being allocated is reported to a memory reporter
+ MemoryAllocated,
+ // when memory being freed is reported to a memory reporter
+ MemoryFreed
+ };
+
+ // When memory is used/freed for tile textures, call this method to update
+ // the value reported by this memory reporter.
+ static void UpdateAmount(MemoryUse action, size_t amount);
+
+ static void UpdateWasteAmount(size_t delta) { sTileWasteAmount += delta; }
+
+ NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize) override {
+ MOZ_COLLECT_REPORT(
+ "gfx-tiles-waste", KIND_OTHER, UNITS_BYTES, int64_t(sTileWasteAmount),
+ "Memory lost due to tiles extending past content boundaries");
+
+ MOZ_COLLECT_REPORT("gfx-textures", KIND_OTHER, UNITS_BYTES,
+ int64_t(sAmount),
+ "Memory used for storing GL textures.");
+
+ MOZ_COLLECT_REPORT("gfx-textures-peak", KIND_OTHER, UNITS_BYTES,
+ int64_t(sPeakAmount),
+ "Peak memory used for storing GL textures.");
+
+ return NS_OK;
+ }
+
+ private:
+ static Atomic<size_t> sAmount;
+ static Atomic<size_t> sPeakAmount;
+ // Count the amount of memory lost to tile waste
+ static Atomic<size_t> sTileWasteAmount;
+};
+
+class GfxTextureWasteTracker {
+ public:
+ GfxTextureWasteTracker() : mBytes(0) {
+ MOZ_COUNT_CTOR(GfxTextureWasteTracker);
+ }
+
+ void Update(int32_t aPixelArea, int32_t aBytesPerPixel) {
+ GfxTexturesReporter::UpdateWasteAmount(-mBytes);
+ mBytes = aPixelArea * aBytesPerPixel;
+ GfxTexturesReporter::UpdateWasteAmount(mBytes);
+ }
+
+ ~GfxTextureWasteTracker() {
+ GfxTexturesReporter::UpdateWasteAmount(-mBytes);
+ MOZ_COUNT_DTOR(GfxTextureWasteTracker);
+ }
+
+ private:
+ GfxTextureWasteTracker(const GfxTextureWasteTracker& aRef);
+
+ int32_t mBytes;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // GFXTEXTURESREPORTER_H_
diff --git a/gfx/gl/HeapCopyOfStackArray.h b/gfx/gl/HeapCopyOfStackArray.h
new file mode 100644
index 0000000000..ffcadde461
--- /dev/null
+++ b/gfx/gl/HeapCopyOfStackArray.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef HEAPCOPYOFSTACKARRAY_H_
+#define HEAPCOPYOFSTACKARRAY_H_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/UniquePtr.h"
+
+#include <string.h>
+
+namespace mozilla {
+
+// Takes a stack array and copies it into a heap buffer.
+// Useful to retain the convenience of declaring static arrays, while
+// avoiding passing stack pointers to the GL (see bug 1005658).
+
+template <typename ElemType>
+class HeapCopyOfStackArray {
+ public:
+ template <size_t N>
+ MOZ_IMPLICIT HeapCopyOfStackArray(const ElemType (&array)[N])
+ : mArrayLength(N), mArrayData(MakeUnique<ElemType[]>(N)) {
+ memcpy(mArrayData.get(), &array[0], N * sizeof(ElemType));
+ }
+
+ ElemType* Data() const { return mArrayData.get(); }
+ size_t ArrayLength() const { return mArrayLength; }
+ size_t ByteLength() const { return mArrayLength * sizeof(ElemType); }
+
+ private:
+ HeapCopyOfStackArray() = delete;
+ HeapCopyOfStackArray(const HeapCopyOfStackArray&) = delete;
+
+ const size_t mArrayLength;
+ UniquePtr<ElemType[]> const mArrayData;
+};
+
+} // namespace mozilla
+
+#endif // HEAPCOPYOFSTACKARRAY_H_
diff --git a/gfx/gl/MozFramebuffer.cpp b/gfx/gl/MozFramebuffer.cpp
new file mode 100644
index 0000000000..10995a7ee1
--- /dev/null
+++ b/gfx/gl/MozFramebuffer.cpp
@@ -0,0 +1,225 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MozFramebuffer.h"
+
+#include "GLContext.h"
+#include "mozilla/gfx/Logging.h"
+#include "ScopedGLHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+static void DeleteByTarget(GLContext* const gl, const GLenum target,
+ const GLuint name) {
+ if (target == LOCAL_GL_RENDERBUFFER) {
+ gl->DeleteRenderbuffer(name);
+ } else {
+ gl->DeleteTexture(name);
+ }
+}
+
+UniquePtr<MozFramebuffer> MozFramebuffer::Create(GLContext* const gl,
+ const gfx::IntSize& size,
+ const uint32_t samples,
+ const bool depthStencil) {
+ if (samples && !gl->IsSupported(GLFeature::framebuffer_multisample))
+ return nullptr;
+
+ if (uint32_t(size.width) > gl->MaxTexOrRbSize() ||
+ uint32_t(size.height) > gl->MaxTexOrRbSize() ||
+ samples > gl->MaxSamples()) {
+ return nullptr;
+ }
+
+ gl->MakeCurrent();
+
+ GLContext::LocalErrorScope errorScope(*gl);
+
+ GLenum colorTarget;
+ GLuint colorName;
+ if (samples) {
+ colorTarget = LOCAL_GL_RENDERBUFFER;
+ colorName = gl->CreateRenderbuffer();
+ const ScopedBindRenderbuffer bindRB(gl, colorName);
+ gl->fRenderbufferStorageMultisample(colorTarget, samples, LOCAL_GL_RGBA8,
+ size.width, size.height);
+ } else {
+ colorTarget = LOCAL_GL_TEXTURE_2D;
+ colorName = gl->CreateTexture();
+ const ScopedBindTexture bindTex(gl, colorName);
+ gl->TexParams_SetClampNoMips();
+ gl->fTexImage2D(colorTarget, 0, LOCAL_GL_RGBA, size.width, size.height, 0,
+ LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, nullptr);
+ }
+
+ const auto err = errorScope.GetError();
+ if (err) {
+ if (err != LOCAL_GL_OUT_OF_MEMORY) {
+ gfxCriticalNote << "Unexpected error: " << gfx::hexa(err) << ": "
+ << GLContext::GLErrorToString(err);
+ }
+ DeleteByTarget(gl, colorTarget, colorName);
+ return nullptr;
+ }
+
+ return CreateImpl(
+ gl, size, samples,
+ depthStencil ? DepthAndStencilBuffer::Create(gl, size, samples) : nullptr,
+ colorTarget, colorName);
+}
+
+UniquePtr<MozFramebuffer> MozFramebuffer::CreateForBacking(
+ GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
+ bool depthStencil, const GLenum colorTarget, const GLuint colorName) {
+ return CreateImpl(
+ gl, size, samples,
+ depthStencil ? DepthAndStencilBuffer::Create(gl, size, samples) : nullptr,
+ colorTarget, colorName);
+}
+
+/* static */ UniquePtr<MozFramebuffer>
+MozFramebuffer::CreateForBackingWithSharedDepthAndStencil(
+ const gfx::IntSize& size, const uint32_t samples, GLenum colorTarget,
+ GLuint colorName,
+ const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer) {
+ auto gl = depthAndStencilBuffer->gl();
+ if (!gl || !gl->MakeCurrent()) {
+ return nullptr;
+ }
+ return CreateImpl(gl, size, samples, depthAndStencilBuffer, colorTarget,
+ colorName);
+}
+
+/* static */ UniquePtr<MozFramebuffer> MozFramebuffer::CreateImpl(
+ GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
+ const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer,
+ const GLenum colorTarget, const GLuint colorName) {
+ GLuint fb = gl->CreateFramebuffer();
+ const ScopedBindFramebuffer bindFB(gl, fb);
+
+ if (colorTarget == LOCAL_GL_RENDERBUFFER) {
+ gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+ LOCAL_GL_COLOR_ATTACHMENT0, colorTarget,
+ colorName);
+ } else {
+ gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ colorTarget, colorName, 0);
+ }
+
+ if (depthAndStencilBuffer) {
+ gl->fFramebufferRenderbuffer(
+ LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER,
+ depthAndStencilBuffer->mDepthRB);
+ gl->fFramebufferRenderbuffer(
+ LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+ LOCAL_GL_RENDERBUFFER, depthAndStencilBuffer->mStencilRB);
+ }
+
+ const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+ if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
+ gfxCriticalNote << "MozFramebuffer::CreateImpl(size:" << size
+ << ", samples:" << samples
+ << ", depthAndStencil:" << bool(depthAndStencilBuffer)
+ << ", colorTarget:" << gfx::hexa(colorTarget)
+ << ", colorName:" << colorName << "): Incomplete: 0x"
+ << gfx::hexa(status);
+ return nullptr;
+ }
+
+ return UniquePtr<MozFramebuffer>(new MozFramebuffer(
+ gl, size, fb, samples, depthAndStencilBuffer, colorTarget, colorName));
+}
+
+/* static */ RefPtr<DepthAndStencilBuffer> DepthAndStencilBuffer::Create(
+ GLContext* const gl, const gfx::IntSize& size, const uint32_t samples) {
+ const auto fnAllocRB = [&](GLenum format) {
+ GLuint rb = gl->CreateRenderbuffer();
+ const ScopedBindRenderbuffer bindRB(gl, rb);
+ if (samples) {
+ gl->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, samples,
+ format, size.width, size.height);
+ } else {
+ gl->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, format, size.width,
+ size.height);
+ }
+ return rb;
+ };
+
+ GLuint depthRB, stencilRB;
+ {
+ GLContext::LocalErrorScope errorScope(*gl);
+
+ if (gl->IsSupported(GLFeature::packed_depth_stencil)) {
+ depthRB = fnAllocRB(LOCAL_GL_DEPTH24_STENCIL8);
+ stencilRB = depthRB; // Ignore unused mStencilRB.
+ } else {
+ depthRB = fnAllocRB(LOCAL_GL_DEPTH_COMPONENT24);
+ stencilRB = fnAllocRB(LOCAL_GL_STENCIL_INDEX8);
+ }
+
+ const auto err = errorScope.GetError();
+ if (err) {
+ MOZ_ASSERT(err == LOCAL_GL_OUT_OF_MEMORY);
+ return nullptr;
+ }
+ }
+
+ return new DepthAndStencilBuffer(gl, size, depthRB, stencilRB);
+}
+
+////////////////////
+
+MozFramebuffer::MozFramebuffer(
+ GLContext* const gl, const gfx::IntSize& size, GLuint fb,
+ const uint32_t samples, RefPtr<DepthAndStencilBuffer> depthAndStencilBuffer,
+ const GLenum colorTarget, const GLuint colorName)
+ : mWeakGL(gl),
+ mSize(size),
+ mSamples(samples),
+ mFB(fb),
+ mColorTarget(colorTarget),
+ mDepthAndStencilBuffer(std::move(depthAndStencilBuffer)),
+ mColorName(colorName) {
+ MOZ_ASSERT(mColorTarget);
+ MOZ_ASSERT(mColorName);
+}
+
+MozFramebuffer::~MozFramebuffer() {
+ GLContext* const gl = mWeakGL;
+ if (!gl || !gl->MakeCurrent()) {
+ return;
+ }
+
+ gl->DeleteFramebuffer(mFB);
+
+ DeleteByTarget(gl, mColorTarget, mColorName);
+}
+
+bool MozFramebuffer::HasDepth() const {
+ return mDepthAndStencilBuffer && mDepthAndStencilBuffer->mDepthRB;
+}
+
+bool MozFramebuffer::HasStencil() const {
+ return mDepthAndStencilBuffer && mDepthAndStencilBuffer->mStencilRB;
+}
+
+DepthAndStencilBuffer::DepthAndStencilBuffer(GLContext* gl,
+ const gfx::IntSize& size,
+ GLuint depthRB, GLuint stencilRB)
+ : mWeakGL(gl), mSize(size), mDepthRB(depthRB), mStencilRB(stencilRB) {}
+
+DepthAndStencilBuffer::~DepthAndStencilBuffer() {
+ GLContext* const gl = mWeakGL;
+ if (!gl || !gl->MakeCurrent()) {
+ return;
+ }
+
+ gl->DeleteRenderbuffer(mDepthRB);
+ gl->DeleteRenderbuffer(mStencilRB);
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/MozFramebuffer.h b/gfx/gl/MozFramebuffer.h
new file mode 100644
index 0000000000..dd51ef6154
--- /dev/null
+++ b/gfx/gl/MozFramebuffer.h
@@ -0,0 +1,109 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZ_FRAMEBUFFER_H_
+#define MOZ_FRAMEBUFFER_H_
+
+#include "gfx2DGlue.h"
+#include "GLConsts.h"
+#include "GLContextTypes.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
+
+namespace mozilla {
+namespace gl {
+
+class DepthAndStencilBuffer final : public SupportsWeakPtr {
+ const WeakPtr<GLContext> mWeakGL;
+ const gfx::IntSize mSize;
+
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DepthAndStencilBuffer)
+
+ const GLuint mDepthRB;
+ const GLuint mStencilRB;
+
+ static RefPtr<DepthAndStencilBuffer> Create(GLContext* const gl,
+ const gfx::IntSize& size,
+ const uint32_t samples);
+
+ RefPtr<GLContext> gl() const { return mWeakGL.get(); }
+
+ // 4 bytes per pixel (24-bit depth + 8-bit stencil).
+ uint64_t EstimateMemory() const {
+ return static_cast<uint64_t>(mSize.width) * 4 * mSize.height;
+ }
+
+ protected:
+ DepthAndStencilBuffer(GLContext* gl, const gfx::IntSize& size, GLuint depthRB,
+ GLuint stencilRB);
+ ~DepthAndStencilBuffer();
+};
+
+class MozFramebuffer final {
+ const WeakPtr<GLContext> mWeakGL;
+
+ public:
+ const gfx::IntSize mSize;
+ const uint32_t mSamples;
+ const GLuint mFB;
+ const GLenum mColorTarget;
+
+ private:
+ const RefPtr<DepthAndStencilBuffer> mDepthAndStencilBuffer;
+ const GLuint mColorName;
+
+ public:
+ // Create a new framebuffer with the specified properties.
+ static UniquePtr<MozFramebuffer> Create(GLContext* gl,
+ const gfx::IntSize& size,
+ uint32_t samples, bool depthStencil);
+
+ // Create a new framebuffer backed by an existing texture or buffer.
+ // Assumes that gl is the current context.
+ static UniquePtr<MozFramebuffer> CreateForBacking(
+ GLContext* gl, const gfx::IntSize& size, uint32_t samples,
+ bool depthStencil, GLenum colorTarget, GLuint colorName);
+
+ // Create a new framebuffer backed by an existing texture or buffer.
+ // Use the same GLContext, size, and samples as framebufferToShareWith.
+ // The new framebuffer will share its depth and stencil buffer with
+ // framebufferToShareWith. The depth and stencil buffers will be destroyed
+ // once the last MozFramebuffer using them is destroyed.
+ static UniquePtr<MozFramebuffer> CreateForBackingWithSharedDepthAndStencil(
+ const gfx::IntSize& size, const uint32_t samples, GLenum colorTarget,
+ GLuint colorName,
+ const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer);
+
+ private:
+ MozFramebuffer(GLContext* gl, const gfx::IntSize& size, GLuint fb,
+ uint32_t samples,
+ RefPtr<DepthAndStencilBuffer> depthAndStencilBuffer,
+ GLenum colorTarget, GLuint colorName);
+
+ // gl must be the current context when this is called.
+ static UniquePtr<MozFramebuffer> CreateImpl(
+ GLContext* const gl, const gfx::IntSize& size, const uint32_t samples,
+ const RefPtr<DepthAndStencilBuffer>& depthAndStencilBuffer,
+ const GLenum colorTarget, const GLuint colorName);
+
+ public:
+ ~MozFramebuffer();
+
+ GLuint ColorTex() const {
+ if (mColorTarget == LOCAL_GL_RENDERBUFFER) return 0;
+ return mColorName;
+ }
+ const auto& GetDepthAndStencilBuffer() const {
+ return mDepthAndStencilBuffer;
+ }
+ bool HasDepth() const;
+ bool HasStencil() const;
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // MOZ_FRAMEBUFFER_H_
diff --git a/gfx/gl/ScopedGLHelpers.cpp b/gfx/gl/ScopedGLHelpers.cpp
new file mode 100644
index 0000000000..d654cae163
--- /dev/null
+++ b/gfx/gl/ScopedGLHelpers.cpp
@@ -0,0 +1,490 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/UniquePtr.h"
+
+#include "GLContext.h"
+#include "ScopedGLHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+/* ScopedGLState - Wraps glEnable/glDisable. **********************************/
+
+// Use |newState = true| to enable, |false| to disable.
+ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState)
+ : mGL(aGL), mCapability(aCapability) {
+ mOldState = mGL->fIsEnabled(mCapability);
+
+ // Early out if we're already in the right state.
+ if (aNewState == mOldState) return;
+
+ if (aNewState) {
+ mGL->fEnable(mCapability);
+ } else {
+ mGL->fDisable(mCapability);
+ }
+}
+
+ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability)
+ : mGL(aGL), mCapability(aCapability) {
+ mOldState = mGL->fIsEnabled(mCapability);
+}
+
+ScopedGLState::~ScopedGLState() {
+ if (mOldState) {
+ mGL->fEnable(mCapability);
+ } else {
+ mGL->fDisable(mCapability);
+ }
+}
+
+/* ScopedBindFramebuffer - Saves and restores with GetUserBoundFB and
+ * BindUserFB. */
+
+void ScopedBindFramebuffer::Init() {
+ if (mGL->IsSupported(GLFeature::split_framebuffer)) {
+ mOldReadFB = mGL->GetReadFB();
+ mOldDrawFB = mGL->GetDrawFB();
+ } else {
+ mOldReadFB = mOldDrawFB = mGL->GetFB();
+ }
+}
+
+ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL) : mGL(aGL) {
+ Init();
+}
+
+ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB)
+ : mGL(aGL) {
+ Init();
+ mGL->BindFB(aNewFB);
+}
+
+ScopedBindFramebuffer::~ScopedBindFramebuffer() {
+ if (mOldReadFB == mOldDrawFB) {
+ mGL->BindFB(mOldDrawFB);
+ } else {
+ mGL->BindDrawFB(mOldDrawFB);
+ mGL->BindReadFB(mOldReadFB);
+ }
+}
+
+/* ScopedBindTextureUnit ******************************************************/
+
+ScopedBindTextureUnit::ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit)
+ : mGL(aGL), mOldTexUnit(0) {
+ MOZ_ASSERT(aTexUnit >= LOCAL_GL_TEXTURE0);
+ mGL->GetUIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &mOldTexUnit);
+ mGL->fActiveTexture(aTexUnit);
+}
+
+ScopedBindTextureUnit::~ScopedBindTextureUnit() {
+ mGL->fActiveTexture(mOldTexUnit);
+}
+
+/* ScopedTexture **************************************************************/
+
+ScopedTexture::ScopedTexture(GLContext* aGL) : mGL(aGL), mTexture(0) {
+ mGL->fGenTextures(1, &mTexture);
+}
+
+ScopedTexture::~ScopedTexture() { mGL->fDeleteTextures(1, &mTexture); }
+
+/* ScopedFramebuffer
+ * **************************************************************/
+
+ScopedFramebuffer::ScopedFramebuffer(GLContext* aGL) : mGL(aGL), mFB(0) {
+ mGL->fGenFramebuffers(1, &mFB);
+}
+
+ScopedFramebuffer::~ScopedFramebuffer() { mGL->fDeleteFramebuffers(1, &mFB); }
+
+/* ScopedRenderbuffer
+ * **************************************************************/
+
+ScopedRenderbuffer::ScopedRenderbuffer(GLContext* aGL) : mGL(aGL), mRB(0) {
+ mGL->fGenRenderbuffers(1, &mRB);
+}
+
+ScopedRenderbuffer::~ScopedRenderbuffer() {
+ mGL->fDeleteRenderbuffers(1, &mRB);
+}
+
+/* ScopedBindTexture **********************************************************/
+
+static GLuint GetBoundTexture(GLContext* gl, GLenum texTarget) {
+ GLenum bindingTarget;
+ switch (texTarget) {
+ case LOCAL_GL_TEXTURE_2D:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D;
+ break;
+
+ case LOCAL_GL_TEXTURE_CUBE_MAP:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_CUBE_MAP;
+ break;
+
+ case LOCAL_GL_TEXTURE_3D:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_3D;
+ break;
+
+ case LOCAL_GL_TEXTURE_2D_ARRAY:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_2D_ARRAY;
+ break;
+
+ case LOCAL_GL_TEXTURE_RECTANGLE_ARB:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
+ break;
+
+ case LOCAL_GL_TEXTURE_EXTERNAL:
+ bindingTarget = LOCAL_GL_TEXTURE_BINDING_EXTERNAL;
+ break;
+
+ default:
+ MOZ_CRASH("bad texTarget");
+ }
+
+ GLuint ret = 0;
+ gl->GetUIntegerv(bindingTarget, &ret);
+ return ret;
+}
+
+ScopedBindTexture::ScopedBindTexture(GLContext* aGL, GLuint aNewTex,
+ GLenum aTarget)
+ : mGL(aGL), mTarget(aTarget), mOldTex(GetBoundTexture(aGL, aTarget)) {
+ mGL->fBindTexture(mTarget, aNewTex);
+}
+
+ScopedBindTexture::~ScopedBindTexture() { mGL->fBindTexture(mTarget, mOldTex); }
+
+/* ScopedBindRenderbuffer *****************************************************/
+
+void ScopedBindRenderbuffer::Init() {
+ mOldRB = 0;
+ mGL->GetUIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &mOldRB);
+}
+
+ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL) : mGL(aGL) {
+ Init();
+}
+
+ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB)
+ : mGL(aGL) {
+ Init();
+ mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, aNewRB);
+}
+
+ScopedBindRenderbuffer::~ScopedBindRenderbuffer() {
+ mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOldRB);
+}
+
+/* ScopedFramebufferForTexture ************************************************/
+ScopedFramebufferForTexture::ScopedFramebufferForTexture(GLContext* aGL,
+ GLuint aTexture,
+ GLenum aTarget)
+ : mGL(aGL), mComplete(false), mFB(0) {
+ mGL->fGenFramebuffers(1, &mFB);
+ ScopedBindFramebuffer autoFB(aGL, mFB);
+ mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+ aTarget, aTexture, 0);
+
+ GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+ if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
+ mComplete = true;
+ } else {
+ mGL->fDeleteFramebuffers(1, &mFB);
+ mFB = 0;
+ }
+}
+
+ScopedFramebufferForTexture::~ScopedFramebufferForTexture() {
+ if (!mFB) return;
+
+ mGL->fDeleteFramebuffers(1, &mFB);
+ mFB = 0;
+}
+
+/* ScopedFramebufferForRenderbuffer *******************************************/
+
+ScopedFramebufferForRenderbuffer::ScopedFramebufferForRenderbuffer(
+ GLContext* aGL, GLuint aRB)
+ : mGL(aGL), mComplete(false), mFB(0) {
+ mGL->fGenFramebuffers(1, &mFB);
+ ScopedBindFramebuffer autoFB(aGL, mFB);
+ mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
+ LOCAL_GL_COLOR_ATTACHMENT0,
+ LOCAL_GL_RENDERBUFFER, aRB);
+
+ GLenum status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
+ if (status == LOCAL_GL_FRAMEBUFFER_COMPLETE) {
+ mComplete = true;
+ } else {
+ mGL->fDeleteFramebuffers(1, &mFB);
+ mFB = 0;
+ }
+}
+
+ScopedFramebufferForRenderbuffer::~ScopedFramebufferForRenderbuffer() {
+ if (!mFB) return;
+
+ mGL->fDeleteFramebuffers(1, &mFB);
+ mFB = 0;
+}
+
+/* ScopedViewportRect *********************************************************/
+
+ScopedViewportRect::ScopedViewportRect(GLContext* aGL, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+ : mGL(aGL) {
+ mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect);
+ mGL->fViewport(x, y, width, height);
+}
+
+ScopedViewportRect::~ScopedViewportRect() {
+ mGL->fViewport(mSavedViewportRect[0], mSavedViewportRect[1],
+ mSavedViewportRect[2], mSavedViewportRect[3]);
+}
+
+/* ScopedScissorRect **********************************************************/
+
+ScopedScissorRect::ScopedScissorRect(GLContext* aGL, GLint x, GLint y,
+ GLsizei width, GLsizei height)
+ : mGL(aGL) {
+ mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
+ mGL->fScissor(x, y, width, height);
+}
+
+ScopedScissorRect::ScopedScissorRect(GLContext* aGL) : mGL(aGL) {
+ mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect);
+}
+
+ScopedScissorRect::~ScopedScissorRect() {
+ mGL->fScissor(mSavedScissorRect[0], mSavedScissorRect[1],
+ mSavedScissorRect[2], mSavedScissorRect[3]);
+}
+
+/* ScopedVertexAttribPointer **************************************************/
+
+ScopedVertexAttribPointer::ScopedVertexAttribPointer(
+ GLContext* aGL, GLuint index, GLint size, GLenum type,
+ realGLboolean normalized, GLsizei stride, GLuint buffer,
+ const GLvoid* pointer)
+ : mGL(aGL),
+ mAttribEnabled(0),
+ mAttribSize(0),
+ mAttribStride(0),
+ mAttribType(0),
+ mAttribNormalized(0),
+ mAttribBufferBinding(0),
+ mAttribPointer(nullptr),
+ mBoundBuffer(0) {
+ WrapImpl(index);
+ mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, buffer);
+ mGL->fVertexAttribPointer(index, size, type, normalized, stride, pointer);
+ mGL->fEnableVertexAttribArray(index);
+}
+
+ScopedVertexAttribPointer::ScopedVertexAttribPointer(GLContext* aGL,
+ GLuint index)
+ : mGL(aGL),
+ mAttribEnabled(0),
+ mAttribSize(0),
+ mAttribStride(0),
+ mAttribType(0),
+ mAttribNormalized(0),
+ mAttribBufferBinding(0),
+ mAttribPointer(nullptr),
+ mBoundBuffer(0) {
+ WrapImpl(index);
+}
+
+void ScopedVertexAttribPointer::WrapImpl(GLuint index) {
+ mAttribIndex = index;
+
+ /*
+ * mGL->fGetVertexAttribiv takes:
+ * VERTEX_ATTRIB_ARRAY_ENABLED
+ * VERTEX_ATTRIB_ARRAY_SIZE,
+ * VERTEX_ATTRIB_ARRAY_STRIDE,
+ * VERTEX_ATTRIB_ARRAY_TYPE,
+ * VERTEX_ATTRIB_ARRAY_NORMALIZED,
+ * VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+ * CURRENT_VERTEX_ATTRIB
+ *
+ * CURRENT_VERTEX_ATTRIB is vertex shader state. \o/
+ * Others appear to be vertex array state,
+ * or alternatively in the internal vertex array state
+ * for a buffer object.
+ */
+
+ mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED,
+ &mAttribEnabled);
+ mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE,
+ &mAttribSize);
+ mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE,
+ &mAttribStride);
+ mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE,
+ &mAttribType);
+ mGL->fGetVertexAttribiv(mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED,
+ &mAttribNormalized);
+ mGL->fGetVertexAttribiv(mAttribIndex,
+ LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING,
+ &mAttribBufferBinding);
+ mGL->fGetVertexAttribPointerv(
+ mAttribIndex, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &mAttribPointer);
+
+ // Note that uniform values are program state, so we don't need to rebind
+ // those.
+
+ mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &mBoundBuffer);
+}
+
+ScopedVertexAttribPointer::~ScopedVertexAttribPointer() {
+ mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mAttribBufferBinding);
+ mGL->fVertexAttribPointer(mAttribIndex, mAttribSize, mAttribType,
+ mAttribNormalized, mAttribStride, mAttribPointer);
+ if (mAttribEnabled)
+ mGL->fEnableVertexAttribArray(mAttribIndex);
+ else
+ mGL->fDisableVertexAttribArray(mAttribIndex);
+ mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundBuffer);
+}
+
+////////////////////////////////////////////////////////////////////////
+// ScopedPackState
+
+ScopedPackState::ScopedPackState(GLContext* gl)
+ : mGL(gl),
+ mAlignment(0),
+ mPixelBuffer(0),
+ mRowLength(0),
+ mSkipPixels(0),
+ mSkipRows(0) {
+ mGL->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mAlignment);
+
+ if (mAlignment != 4) mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4);
+
+ if (!mGL->HasPBOState()) return;
+
+ mGL->fGetIntegerv(LOCAL_GL_PIXEL_PACK_BUFFER_BINDING, (GLint*)&mPixelBuffer);
+ mGL->fGetIntegerv(LOCAL_GL_PACK_ROW_LENGTH, &mRowLength);
+ mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_PIXELS, &mSkipPixels);
+ mGL->fGetIntegerv(LOCAL_GL_PACK_SKIP_ROWS, &mSkipRows);
+
+ if (mPixelBuffer != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, 0);
+ if (mRowLength != 0) mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, 0);
+ if (mSkipPixels != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, 0);
+ if (mSkipRows != 0) mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, 0);
+}
+
+bool ScopedPackState::SetForWidthAndStrideRGBA(GLsizei aWidth,
+ GLsizei aStride) {
+ MOZ_ASSERT(aStride % 4 == 0, "RGBA data should always be 4-byte aligned");
+ MOZ_ASSERT(aStride / 4 >= aWidth, "Stride too small");
+ if (aStride / 4 == aWidth) {
+ // No special handling needed.
+ return true;
+ }
+ if (mGL->HasPBOState()) {
+ // HasPBOState implies support for GL_PACK_ROW_LENGTH.
+ mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, aStride / 4);
+ return true;
+ }
+ return false;
+}
+
+ScopedPackState::~ScopedPackState() {
+ mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mAlignment);
+
+ if (!mGL->HasPBOState()) return;
+
+ mGL->fBindBuffer(LOCAL_GL_PIXEL_PACK_BUFFER, mPixelBuffer);
+ mGL->fPixelStorei(LOCAL_GL_PACK_ROW_LENGTH, mRowLength);
+ mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_PIXELS, mSkipPixels);
+ mGL->fPixelStorei(LOCAL_GL_PACK_SKIP_ROWS, mSkipRows);
+}
+
+////////////////////////////////////////////////////////////////////////
+// ResetUnpackState
+
+ResetUnpackState::ResetUnpackState(GLContext* gl)
+ : mGL(gl),
+ mAlignment(0),
+ mPBO(0),
+ mRowLength(0),
+ mImageHeight(0),
+ mSkipPixels(0),
+ mSkipRows(0),
+ mSkipImages(0) {
+ const auto fnReset = [&](GLenum pname, GLuint val, GLuint* const out_old) {
+ mGL->GetUIntegerv(pname, out_old);
+ if (*out_old != val) {
+ mGL->fPixelStorei(pname, val);
+ }
+ };
+
+ // Default is 4, but 1 is more useful.
+ fnReset(LOCAL_GL_UNPACK_ALIGNMENT, 1, &mAlignment);
+
+ if (!mGL->HasPBOState()) return;
+
+ mGL->GetUIntegerv(LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING, &mPBO);
+ if (mPBO != 0) mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, 0);
+
+ fnReset(LOCAL_GL_UNPACK_ROW_LENGTH, 0, &mRowLength);
+ fnReset(LOCAL_GL_UNPACK_IMAGE_HEIGHT, 0, &mImageHeight);
+ fnReset(LOCAL_GL_UNPACK_SKIP_PIXELS, 0, &mSkipPixels);
+ fnReset(LOCAL_GL_UNPACK_SKIP_ROWS, 0, &mSkipRows);
+ fnReset(LOCAL_GL_UNPACK_SKIP_IMAGES, 0, &mSkipImages);
+}
+
+ResetUnpackState::~ResetUnpackState() {
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, mAlignment);
+
+ if (!mGL->HasPBOState()) return;
+
+ mGL->fBindBuffer(LOCAL_GL_PIXEL_UNPACK_BUFFER, mPBO);
+
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_ROW_LENGTH, mRowLength);
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_IMAGE_HEIGHT, mImageHeight);
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_PIXELS, mSkipPixels);
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_ROWS, mSkipRows);
+ mGL->fPixelStorei(LOCAL_GL_UNPACK_SKIP_IMAGES, mSkipImages);
+}
+
+////////////////////////////////////////////////////////////////////////
+// ScopedBindPBO
+
+static GLuint GetPBOBinding(GLContext* gl, GLenum target) {
+ if (!gl->HasPBOState()) return 0;
+
+ GLenum targetBinding;
+ switch (target) {
+ case LOCAL_GL_PIXEL_PACK_BUFFER:
+ targetBinding = LOCAL_GL_PIXEL_PACK_BUFFER_BINDING;
+ break;
+
+ case LOCAL_GL_PIXEL_UNPACK_BUFFER:
+ targetBinding = LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING;
+ break;
+
+ default:
+ MOZ_CRASH();
+ }
+
+ return gl->GetIntAs<GLuint>(targetBinding);
+}
+
+ScopedBindPBO::ScopedBindPBO(GLContext* gl, GLenum target)
+ : mGL(gl), mTarget(target), mPBO(GetPBOBinding(mGL, mTarget)) {}
+
+ScopedBindPBO::~ScopedBindPBO() {
+ if (!mGL->HasPBOState()) return;
+
+ mGL->fBindBuffer(mTarget, mPBO);
+}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/ScopedGLHelpers.h b/gfx/gl/ScopedGLHelpers.h
new file mode 100644
index 0000000000..6e3b9867bc
--- /dev/null
+++ b/gfx/gl/ScopedGLHelpers.h
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SCOPEDGLHELPERS_H_
+#define SCOPEDGLHELPERS_H_
+
+#include "GLDefs.h"
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+namespace gl {
+
+class GLContext;
+
+#ifdef DEBUG
+bool IsContextCurrent(GLContext* gl);
+#endif
+
+// Wraps glEnable/Disable.
+struct ScopedGLState final {
+ private:
+ GLContext* const mGL;
+ const GLenum mCapability;
+ bool mOldState;
+
+ public:
+ // Use |newState = true| to enable, |false| to disable.
+ ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState);
+ // variant that doesn't change state; simply records existing state to be
+ // restored by the destructor
+ ScopedGLState(GLContext* aGL, GLenum aCapability);
+ ~ScopedGLState();
+};
+
+// Saves and restores with GetUserBoundFB and BindUserFB.
+struct ScopedBindFramebuffer final {
+ private:
+ GLContext* const mGL;
+ GLuint mOldReadFB;
+ GLuint mOldDrawFB;
+
+ void Init();
+
+ public:
+ explicit ScopedBindFramebuffer(GLContext* aGL);
+ ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB);
+ ~ScopedBindFramebuffer();
+};
+
+struct ScopedBindTextureUnit final {
+ private:
+ GLContext* const mGL;
+ GLenum mOldTexUnit;
+
+ public:
+ ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit);
+ ~ScopedBindTextureUnit();
+};
+
+struct ScopedTexture final {
+ private:
+ GLContext* const mGL;
+ GLuint mTexture;
+
+ public:
+ explicit ScopedTexture(GLContext* aGL);
+ ~ScopedTexture();
+
+ GLuint Texture() const { return mTexture; }
+ operator GLuint() const { return mTexture; }
+};
+
+struct ScopedFramebuffer final {
+ private:
+ GLContext* const mGL;
+ GLuint mFB;
+
+ public:
+ explicit ScopedFramebuffer(GLContext* aGL);
+ ~ScopedFramebuffer();
+
+ const auto& FB() const { return mFB; }
+ operator GLuint() const { return mFB; }
+};
+
+struct ScopedRenderbuffer final {
+ private:
+ GLContext* const mGL;
+ GLuint mRB;
+
+ public:
+ explicit ScopedRenderbuffer(GLContext* aGL);
+ ~ScopedRenderbuffer();
+
+ GLuint RB() { return mRB; }
+ operator GLuint() const { return mRB; }
+};
+
+struct ScopedBindTexture final {
+ private:
+ GLContext* const mGL;
+ const GLenum mTarget;
+ const GLuint mOldTex;
+
+ public:
+ ScopedBindTexture(GLContext* aGL, GLuint aNewTex,
+ GLenum aTarget = LOCAL_GL_TEXTURE_2D);
+ ~ScopedBindTexture();
+};
+
+struct ScopedBindRenderbuffer final {
+ private:
+ GLContext* const mGL;
+ GLuint mOldRB;
+
+ private:
+ void Init();
+
+ public:
+ explicit ScopedBindRenderbuffer(GLContext* aGL);
+ ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB);
+ ~ScopedBindRenderbuffer();
+};
+
+struct ScopedFramebufferForTexture final {
+ private:
+ GLContext* const mGL;
+ bool mComplete; // True if the framebuffer we create is complete.
+ GLuint mFB;
+
+ public:
+ ScopedFramebufferForTexture(GLContext* aGL, GLuint aTexture,
+ GLenum aTarget = LOCAL_GL_TEXTURE_2D);
+ ~ScopedFramebufferForTexture();
+
+ bool IsComplete() const { return mComplete; }
+
+ GLuint FB() const {
+ MOZ_GL_ASSERT(mGL, IsComplete());
+ return mFB;
+ }
+};
+
+struct ScopedFramebufferForRenderbuffer final {
+ private:
+ GLContext* const mGL;
+ bool mComplete; // True if the framebuffer we create is complete.
+ GLuint mFB;
+
+ public:
+ ScopedFramebufferForRenderbuffer(GLContext* aGL, GLuint aRB);
+ ~ScopedFramebufferForRenderbuffer();
+
+ bool IsComplete() const { return mComplete; }
+ GLuint FB() const {
+ MOZ_GL_ASSERT(mGL, IsComplete());
+ return mFB;
+ }
+};
+
+struct ScopedViewportRect final {
+ private:
+ GLContext* const mGL;
+ GLint mSavedViewportRect[4];
+
+ public:
+ ScopedViewportRect(GLContext* aGL, GLint x, GLint y, GLsizei width,
+ GLsizei height);
+ ~ScopedViewportRect();
+};
+
+struct ScopedScissorRect final {
+ private:
+ GLContext* const mGL;
+ GLint mSavedScissorRect[4];
+
+ public:
+ ScopedScissorRect(GLContext* aGL, GLint x, GLint y, GLsizei width,
+ GLsizei height);
+ explicit ScopedScissorRect(GLContext* aGL);
+ ~ScopedScissorRect();
+};
+
+struct ScopedVertexAttribPointer final {
+ private:
+ GLContext* const mGL;
+ GLuint mAttribIndex;
+ GLint mAttribEnabled;
+ GLint mAttribSize;
+ GLint mAttribStride;
+ GLint mAttribType;
+ GLint mAttribNormalized;
+ GLint mAttribBufferBinding;
+ void* mAttribPointer;
+ GLuint mBoundBuffer;
+
+ public:
+ ScopedVertexAttribPointer(GLContext* aGL, GLuint index, GLint size,
+ GLenum type, realGLboolean normalized,
+ GLsizei stride, GLuint buffer,
+ const GLvoid* pointer);
+ explicit ScopedVertexAttribPointer(GLContext* aGL, GLuint index);
+ ~ScopedVertexAttribPointer();
+
+ private:
+ void WrapImpl(GLuint index);
+};
+
+struct ScopedPackState final {
+ private:
+ GLContext* const mGL;
+ GLint mAlignment;
+
+ GLuint mPixelBuffer;
+ GLint mRowLength;
+ GLint mSkipPixels;
+ GLint mSkipRows;
+
+ public:
+ explicit ScopedPackState(GLContext* gl);
+ ~ScopedPackState();
+
+ // Returns whether the stride was handled successfully.
+ bool SetForWidthAndStrideRGBA(GLsizei aWidth, GLsizei aStride);
+};
+
+struct ResetUnpackState final {
+ private:
+ GLContext* const mGL;
+ GLuint mAlignment;
+
+ GLuint mPBO;
+ GLuint mRowLength;
+ GLuint mImageHeight;
+ GLuint mSkipPixels;
+ GLuint mSkipRows;
+ GLuint mSkipImages;
+
+ public:
+ explicit ResetUnpackState(GLContext* gl);
+ ~ResetUnpackState();
+};
+
+struct ScopedBindPBO final {
+ private:
+ GLContext* const mGL;
+ const GLenum mTarget;
+ const GLuint mPBO;
+
+ public:
+ ScopedBindPBO(GLContext* gl, GLenum target);
+ ~ScopedBindPBO();
+};
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* SCOPEDGLHELPERS_H_ */
diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp
new file mode 100644
index 0000000000..2fbfd3f625
--- /dev/null
+++ b/gfx/gl/SharedSurface.cpp
@@ -0,0 +1,153 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurface.h"
+
+#include "../2d/2D.h"
+#include "GLBlitHelper.h"
+#include "GLContext.h"
+#include "GLReadTexImageHelper.h"
+#include "GLScreenBuffer.h"
+#include "nsThreadUtils.h"
+#include "ScopedGLHelpers.h"
+#include "SharedSurfaceGL.h"
+#include "SharedSurfaceEGL.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/layers/CompositorTypes.h"
+#include "mozilla/layers/TextureClientSharedSurface.h"
+#include "mozilla/layers/TextureForwarder.h"
+#include "mozilla/StaticPrefs_webgl.h"
+#include "mozilla/Unused.h"
+#include "VRManagerChild.h"
+
+#ifdef XP_WIN
+# include "SharedSurfaceANGLE.h"
+# include "SharedSurfaceD3D11Interop.h"
+#endif
+
+#ifdef XP_MACOSX
+# include "SharedSurfaceIO.h"
+#endif
+
+#ifdef MOZ_WIDGET_GTK
+# include "gfxPlatformGtk.h"
+# include "SharedSurfaceDMABUF.h"
+# include "mozilla/widget/DMABufLibWrapper.h"
+#endif
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "SharedSurfaceAndroidHardwareBuffer.h"
+#endif
+
+namespace mozilla {
+namespace gl {
+
+////////////////////////////////////////////////////////////////////////
+// SharedSurface
+
+SharedSurface::SharedSurface(const SharedSurfaceDesc& desc,
+ UniquePtr<MozFramebuffer> fb)
+ : mDesc(desc), mFb(std::move(fb)) {}
+
+SharedSurface::~SharedSurface() = default;
+
+void SharedSurface::LockProd() {
+ MOZ_ASSERT(!mIsLocked);
+
+ LockProdImpl();
+
+ mDesc.gl->LockSurface(this);
+ mIsLocked = true;
+}
+
+void SharedSurface::UnlockProd() {
+ if (!mIsLocked) return;
+
+ UnlockProdImpl();
+
+ mDesc.gl->UnlockSurface(this);
+ mIsLocked = false;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceFactory
+
+/* static */
+UniquePtr<SurfaceFactory> SurfaceFactory::Create(
+ GLContext* const pGl, const layers::TextureType consumerType) {
+ auto& gl = *pGl;
+
+ switch (consumerType) {
+ case layers::TextureType::D3D11:
+#ifdef XP_WIN
+ if (gl.IsANGLE()) {
+ return SurfaceFactory_ANGLEShareHandle::Create(gl);
+ }
+ if (StaticPrefs::webgl_dxgl_enabled()) {
+ return SurfaceFactory_D3D11Interop::Create(gl);
+ }
+#endif
+ return nullptr;
+
+ case layers::TextureType::MacIOSurface:
+#ifdef XP_MACOSX
+ return MakeUnique<SurfaceFactory_IOSurface>(gl);
+#else
+ return nullptr;
+#endif
+
+ case layers::TextureType::DMABUF:
+#ifdef MOZ_WIDGET_GTK
+ if (gl.GetContextType() == GLContextType::EGL &&
+ widget::DMABufDevice::IsDMABufWebGLEnabled()) {
+ return SurfaceFactory_DMABUF::Create(gl);
+ }
+#endif
+ return nullptr;
+
+ case layers::TextureType::AndroidNativeWindow:
+#ifdef MOZ_WIDGET_ANDROID
+ return MakeUnique<SurfaceFactory_SurfaceTexture>(gl);
+#else
+ return nullptr;
+#endif
+
+ case layers::TextureType::AndroidHardwareBuffer:
+#ifdef MOZ_WIDGET_ANDROID
+ if (XRE_IsGPUProcess()) {
+ // Enable SharedSurface of AndroidHardwareBuffer only in GPU process.
+ return SurfaceFactory_AndroidHardwareBuffer::Create(gl);
+ }
+#endif
+ return nullptr;
+
+ case layers::TextureType::EGLImage:
+#ifdef MOZ_WIDGET_ANDROID
+ if (XRE_IsParentProcess()) {
+ return SurfaceFactory_EGLImage::Create(gl);
+ }
+#endif
+ return nullptr;
+
+ case layers::TextureType::Unknown:
+ case layers::TextureType::Last:
+ break;
+ }
+
+#ifdef MOZ_X11
+ // Silence a warning.
+ Unused << gl;
+#endif
+
+ return nullptr;
+}
+
+SurfaceFactory::SurfaceFactory(const PartialSharedSurfaceDesc& partialDesc)
+ : mDesc(partialDesc), mMutex("SurfaceFactor::mMutex") {}
+
+SurfaceFactory::~SurfaceFactory() = default;
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h
new file mode 100644
index 0000000000..4168de69a2
--- /dev/null
+++ b/gfx/gl/SharedSurface.h
@@ -0,0 +1,199 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* SharedSurface abstracts an actual surface (can be a GL texture, but
+ * not necessarily) that handles sharing.
+ * Its specializations are:
+ * SharedSurface_Basic (client-side bitmap, does readback)
+ * SharedSurface_GLTexture
+ * SharedSurface_EGLImage
+ * SharedSurface_ANGLEShareHandle
+ */
+
+#ifndef SHARED_SURFACE_H_
+#define SHARED_SURFACE_H_
+
+#include <queue>
+#include <set>
+#include <stdint.h>
+
+#include "GLContext.h" // Bug 1635644
+#include "GLContextTypes.h"
+#include "GLDefs.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WeakPtr.h"
+#include "SurfaceTypes.h"
+
+class nsIThread;
+
+namespace mozilla {
+namespace gfx {
+class DataSourceSurface;
+class DrawTarget;
+} // namespace gfx
+
+namespace layers {
+class KnowsCompositor;
+enum class LayersBackend : int8_t;
+class LayersIPCChannel;
+class SharedSurfaceTextureClient;
+class SurfaceDescriptor;
+class TextureClient;
+enum class TextureFlags : uint32_t;
+enum class TextureType : int8_t;
+} // namespace layers
+
+namespace gl {
+
+class MozFramebuffer;
+struct ScopedBindFramebuffer;
+class SurfaceFactory;
+
+struct PartialSharedSurfaceDesc {
+ const WeakPtr<GLContext> gl;
+ const SharedSurfaceType type;
+ const layers::TextureType consumerType;
+ const bool canRecycle;
+
+ bool operator==(const PartialSharedSurfaceDesc& rhs) const {
+ return gl == rhs.gl && type == rhs.type &&
+ consumerType == rhs.consumerType && canRecycle == rhs.canRecycle;
+ }
+};
+struct SharedSurfaceDesc : public PartialSharedSurfaceDesc {
+ gfx::IntSize size = {};
+ gfx::ColorSpace2 colorSpace = gfx::ColorSpace2::UNKNOWN;
+
+ bool operator==(const SharedSurfaceDesc& rhs) const {
+ return PartialSharedSurfaceDesc::operator==(rhs) && size == rhs.size &&
+ colorSpace == rhs.colorSpace;
+ }
+ bool operator!=(const SharedSurfaceDesc& rhs) const {
+ return !(*this == rhs);
+ }
+};
+
+class SharedSurface {
+ public:
+ const SharedSurfaceDesc mDesc;
+ const UniquePtr<MozFramebuffer> mFb; // null if we should use fb=0.
+
+ protected:
+ bool mIsLocked = false;
+ bool mIsProducerAcquired = false;
+
+ SharedSurface(const SharedSurfaceDesc&, UniquePtr<MozFramebuffer>);
+
+ public:
+ virtual ~SharedSurface();
+
+ bool IsLocked() const { return mIsLocked; }
+ bool IsProducerAcquired() const { return mIsProducerAcquired; }
+
+ // This locks the SharedSurface as the production buffer for the context.
+ // This is needed by backends which use PBuffers and/or EGLSurfaces.
+ void LockProd();
+
+ // Unlocking is harmless if we're already unlocked.
+ void UnlockProd();
+
+ // This surface has been moved to the front buffer and will not be locked
+ // again until it is recycled. Do any finalization steps here.
+ virtual void Commit() {}
+
+ protected:
+ virtual void LockProdImpl(){};
+ virtual void UnlockProdImpl(){};
+
+ virtual void ProducerAcquireImpl(){};
+ virtual void ProducerReleaseImpl(){};
+
+ virtual void ProducerReadAcquireImpl() { ProducerAcquireImpl(); }
+ virtual void ProducerReadReleaseImpl() { ProducerReleaseImpl(); }
+
+ public:
+ void ProducerAcquire() {
+ MOZ_ASSERT(!mIsProducerAcquired);
+ ProducerAcquireImpl();
+ mIsProducerAcquired = true;
+ }
+ void ProducerRelease() {
+ MOZ_ASSERT(mIsProducerAcquired);
+ ProducerReleaseImpl();
+ mIsProducerAcquired = false;
+ }
+ void ProducerReadAcquire() {
+ MOZ_ASSERT(!mIsProducerAcquired);
+ ProducerReadAcquireImpl();
+ mIsProducerAcquired = true;
+ }
+ void ProducerReadRelease() {
+ MOZ_ASSERT(mIsProducerAcquired);
+ ProducerReadReleaseImpl();
+ mIsProducerAcquired = false;
+ }
+
+ // This function waits until the buffer is no longer being used.
+ // To optimize the performance, some implementaions recycle SharedSurfaces
+ // even when its buffer is still being used.
+ virtual void WaitForBufferOwnership() {}
+
+ // Returns true if the buffer is available.
+ // You can call WaitForBufferOwnership to wait for availability.
+ virtual bool IsBufferAvailable() const { return true; }
+
+ virtual bool NeedsIndirectReads() const { return false; }
+
+ // Returns true if the surface is still valid to use. If false, the underlying
+ // resource has been released and we must allocate a new surface instead.
+ virtual bool IsValid() const { return true; };
+
+ virtual Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() = 0;
+};
+
+// -
+
+class SurfaceFactory {
+ public:
+ const PartialSharedSurfaceDesc mDesc;
+
+ layers::TextureType GetConsumerType() const { return mDesc.consumerType; }
+
+ protected:
+ Mutex mMutex MOZ_UNANNOTATED;
+
+ public:
+ static UniquePtr<SurfaceFactory> Create(GLContext*, layers::TextureType);
+
+ protected:
+ explicit SurfaceFactory(const PartialSharedSurfaceDesc&);
+
+ public:
+ virtual ~SurfaceFactory();
+
+ protected:
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc&) = 0;
+
+ public:
+ UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size,
+ gfx::ColorSpace2 cs) {
+ return CreateSharedImpl({mDesc, size, cs});
+ }
+};
+
+template <typename T>
+inline UniquePtr<T> AsUnique(T* const p) {
+ return UniquePtr<T>(p);
+}
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // SHARED_SURFACE_H_
diff --git a/gfx/gl/SharedSurfaceANGLE.cpp b/gfx/gl/SharedSurfaceANGLE.cpp
new file mode 100644
index 0000000000..8fae962b9f
--- /dev/null
+++ b/gfx/gl/SharedSurfaceANGLE.cpp
@@ -0,0 +1,215 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceANGLE.h"
+
+#include <d3d11.h>
+#include "GLContextEGL.h"
+#include "GLLibraryEGL.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/gfx/FileHandleWrapper.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+
+namespace mozilla {
+namespace gl {
+
+static ID3D11Device* GetD3D11DeviceOfEGLDisplay(GLContextEGL* gle) {
+ const auto& egl = gle->mEgl;
+ MOZ_ASSERT(egl);
+ if (!egl ||
+ !egl->mLib->IsExtensionSupported(gl::EGLLibExtension::EXT_device_query)) {
+ return nullptr;
+ }
+
+ // Fetch the D3D11 device.
+ EGLDeviceEXT eglDevice = nullptr;
+ egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
+ MOZ_ASSERT(eglDevice);
+ ID3D11Device* device = nullptr;
+ egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
+ (EGLAttrib*)&device);
+ if (!device) {
+ return nullptr;
+ }
+ return device;
+}
+
+// Returns `EGL_NO_SURFACE` (`0`) on error.
+static EGLSurface CreatePBufferSurface(EglDisplay* egl, EGLConfig config,
+ const gfx::IntSize& size,
+ RefPtr<ID3D11Texture2D> texture2D) {
+ const EGLint attribs[] = {LOCAL_EGL_WIDTH, size.width, LOCAL_EGL_HEIGHT,
+ size.height, LOCAL_EGL_NONE};
+ const auto buffer = reinterpret_cast<EGLClientBuffer>(texture2D.get());
+
+ EGLSurface surface = egl->fCreatePbufferFromClientBuffer(
+ LOCAL_EGL_D3D_TEXTURE_ANGLE, buffer, config, attribs);
+ if (!surface) {
+ EGLint err = egl->mLib->fGetError();
+ gfxCriticalError() << "Failed to create Pbuffer surface error: "
+ << gfx::hexa(err) << " Size : " << size;
+ return 0;
+ }
+
+ return surface;
+}
+
+/*static*/
+UniquePtr<SharedSurface_ANGLEShareHandle>
+SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
+ const auto& gle = GLContextEGL::Cast(desc.gl);
+ const auto& egl = gle->mEgl;
+ MOZ_ASSERT(egl);
+ MOZ_ASSERT(egl->IsExtensionSupported(
+ EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle));
+
+ auto* device = GetD3D11DeviceOfEGLDisplay(gle);
+ if (!device) {
+ return nullptr;
+ }
+
+ // Create a texture in case we need to readback.
+ const DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ CD3D11_TEXTURE2D_DESC texDesc(
+ format, desc.size.width, desc.size.height, 1, 1,
+ D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
+ texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
+ D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
+
+ RefPtr<ID3D11Texture2D> texture2D;
+ auto hr =
+ device->CreateTexture2D(&texDesc, nullptr, getter_AddRefs(texture2D));
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ RefPtr<IDXGIResource1> texDXGI;
+ hr = texture2D->QueryInterface(__uuidof(IDXGIResource1),
+ getter_AddRefs(texDXGI));
+ if (FAILED(hr)) {
+ return nullptr;
+ }
+
+ HANDLE sharedHandle = nullptr;
+ texDXGI->CreateSharedHandle(
+ nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
+ &sharedHandle);
+
+ RefPtr<gfx::FileHandleWrapper> handle =
+ new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle));
+
+ RefPtr<IDXGIKeyedMutex> keyedMutex;
+ texture2D->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(keyedMutex));
+ if (!keyedMutex) {
+ return nullptr;
+ }
+
+ const auto& config = gle->mSurfaceConfig;
+ MOZ_ASSERT(config);
+
+ EGLSurface pbuffer =
+ CreatePBufferSurface(egl.get(), config, desc.size, texture2D);
+ if (!pbuffer) return nullptr;
+
+ return AsUnique(new SharedSurface_ANGLEShareHandle(
+ desc, egl, pbuffer, std::move(handle), keyedMutex));
+}
+
+SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(
+ const SharedSurfaceDesc& desc, const std::weak_ptr<EglDisplay>& egl,
+ EGLSurface pbuffer, RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
+ const RefPtr<IDXGIKeyedMutex>& keyedMutex)
+ : SharedSurface(desc, nullptr),
+ mEGL(egl),
+ mPBuffer(pbuffer),
+ mSharedHandle(std::move(aSharedHandle)),
+ mKeyedMutex(keyedMutex) {}
+
+SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() {
+ const auto& gl = mDesc.gl;
+
+ if (gl && GLContextEGL::Cast(gl)->GetEGLSurfaceOverride() == mPBuffer) {
+ GLContextEGL::Cast(gl)->SetEGLSurfaceOverride(EGL_NO_SURFACE);
+ }
+ const auto egl = mEGL.lock();
+ if (egl) {
+ egl->fDestroySurface(mPBuffer);
+ }
+}
+
+void SharedSurface_ANGLEShareHandle::LockProdImpl() {
+ const auto& gl = mDesc.gl;
+ GLContextEGL::Cast(gl)->SetEGLSurfaceOverride(mPBuffer);
+}
+
+void SharedSurface_ANGLEShareHandle::UnlockProdImpl() {}
+
+void SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() {
+ HRESULT hr = mKeyedMutex->AcquireSync(0, 10000);
+ if (hr == WAIT_TIMEOUT) {
+ MOZ_CRASH("GFX: ANGLE share handle timeout");
+ }
+}
+
+void SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() {
+ const auto& gl = mDesc.gl;
+ // XXX: ReleaseSync() has an implicit flush of the D3D commands
+ // whether we need Flush() or not depends on the ANGLE semantics.
+ // For now, we'll just do it
+ gl->fFlush();
+ mKeyedMutex->ReleaseSync(0);
+}
+
+void SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() {
+ ProducerAcquireImpl();
+}
+
+void SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() {
+ mKeyedMutex->ReleaseSync(0);
+}
+
+Maybe<layers::SurfaceDescriptor>
+SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor() {
+ const auto format = gfx::SurfaceFormat::B8G8R8A8;
+ return Some(layers::SurfaceDescriptorD3D10(
+ mSharedHandle, /* gpuProcessTextureId */ Nothing(),
+ /* arrayIndex */ 0, format, mDesc.size, mDesc.colorSpace,
+ gfx::ColorRange::FULL, /* hasKeyedMutex */ true,
+ /* fenceInfo */ Nothing(), /* gpuProcessQueryId */ Nothing()));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Factory
+
+/*static*/
+UniquePtr<SurfaceFactory_ANGLEShareHandle>
+SurfaceFactory_ANGLEShareHandle::Create(GLContext& gl) {
+ if (!gl.IsANGLE()) return nullptr;
+
+ const auto& gle = *GLContextEGL::Cast(&gl);
+ const auto& egl = gle.mEgl;
+
+ if (!egl->IsExtensionSupported(
+ EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle)) {
+ return nullptr;
+ }
+
+ if (XRE_IsContentProcess()) {
+ gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
+ }
+
+ gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get();
+ MOZ_ASSERT(dm);
+ if (gl.IsWARP() != dm->IsWARP() || !dm->TextureSharingWorks()) {
+ return nullptr;
+ }
+
+ return AsUnique(new SurfaceFactory_ANGLEShareHandle(
+ {&gl, SharedSurfaceType::EGLSurfaceANGLE, layers::TextureType::D3D11,
+ true}));
+}
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h
new file mode 100644
index 0000000000..5a1a617338
--- /dev/null
+++ b/gfx/gl/SharedSurfaceANGLE.h
@@ -0,0 +1,75 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_ANGLE_H_
+#define SHARED_SURFACE_ANGLE_H_
+
+#include <windows.h>
+#include <memory>
+#include "SharedSurface.h"
+
+struct IDXGIKeyedMutex;
+struct ID3D11Texture2D;
+
+namespace mozilla {
+
+namespace gfx {
+class FileHandleWrapper;
+} // namespace gfx
+
+namespace gl {
+
+class GLContext;
+class EglDisplay;
+
+class SharedSurface_ANGLEShareHandle final : public SharedSurface {
+ public:
+ const std::weak_ptr<EglDisplay> mEGL;
+ const EGLSurface mPBuffer;
+ const RefPtr<gfx::FileHandleWrapper> mSharedHandle;
+ const RefPtr<IDXGIKeyedMutex> mKeyedMutex;
+
+ static UniquePtr<SharedSurface_ANGLEShareHandle> Create(
+ const SharedSurfaceDesc&);
+
+ private:
+ SharedSurface_ANGLEShareHandle(const SharedSurfaceDesc&,
+ const std::weak_ptr<EglDisplay>& egl,
+ EGLSurface pbuffer,
+ RefPtr<gfx::FileHandleWrapper>&& aSharedHandle,
+ const RefPtr<IDXGIKeyedMutex>& keyedMutex);
+
+ public:
+ virtual ~SharedSurface_ANGLEShareHandle();
+
+ virtual void LockProdImpl() override;
+ virtual void UnlockProdImpl() override;
+
+ virtual void ProducerAcquireImpl() override;
+ virtual void ProducerReleaseImpl() override;
+ virtual void ProducerReadAcquireImpl() override;
+ virtual void ProducerReadReleaseImpl() override;
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+};
+
+class SurfaceFactory_ANGLEShareHandle final : public SurfaceFactory {
+ public:
+ static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext& gl);
+
+ private:
+ explicit SurfaceFactory_ANGLEShareHandle(const PartialSharedSurfaceDesc& desc)
+ : SurfaceFactory(desc) {}
+
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_ANGLEShareHandle::Create(desc);
+ }
+};
+
+} // namespace gl
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_ANGLE_H_ */
diff --git a/gfx/gl/SharedSurfaceAndroidHardwareBuffer.cpp b/gfx/gl/SharedSurfaceAndroidHardwareBuffer.cpp
new file mode 100644
index 0000000000..00f925ce75
--- /dev/null
+++ b/gfx/gl/SharedSurfaceAndroidHardwareBuffer.cpp
@@ -0,0 +1,168 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceAndroidHardwareBuffer.h"
+
+#include "GLBlitHelper.h"
+#include "GLContextEGL.h"
+#include "GLContextProvider.h"
+#include "GLLibraryEGL.h"
+#include "GLReadTexImageHelper.h"
+#include "MozFramebuffer.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+#include "mozilla/layers/AndroidHardwareBuffer.h"
+#include "ScopedGLHelpers.h"
+#include "SharedSurface.h"
+
+namespace mozilla {
+namespace gl {
+
+/*static*/
+UniquePtr<SharedSurface_AndroidHardwareBuffer>
+SharedSurface_AndroidHardwareBuffer::Create(const SharedSurfaceDesc& desc) {
+ const auto& gle = GLContextEGL::Cast(desc.gl);
+ const auto& egl = gle->mEgl;
+
+ RefPtr<layers::AndroidHardwareBuffer> buffer =
+ layers::AndroidHardwareBuffer::Create(desc.size,
+ gfx::SurfaceFormat::R8G8B8A8);
+ if (!buffer) {
+ return nullptr;
+ }
+
+ const EGLint attrs[] = {
+ LOCAL_EGL_IMAGE_PRESERVED,
+ LOCAL_EGL_TRUE,
+ LOCAL_EGL_NONE,
+ LOCAL_EGL_NONE,
+ };
+
+ EGLClientBuffer clientBuffer =
+ egl->mLib->fGetNativeClientBufferANDROID(buffer->GetNativeBuffer());
+ const auto image = egl->fCreateImage(
+ EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
+ if (!image) {
+ return nullptr;
+ }
+
+ auto tex = MakeUnique<Texture>(*desc.gl);
+ {
+ ScopedBindTexture texture(gle, tex->name, LOCAL_GL_TEXTURE_2D);
+ gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER,
+ LOCAL_GL_LINEAR);
+ gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER,
+ LOCAL_GL_LINEAR);
+ gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S,
+ LOCAL_GL_CLAMP_TO_EDGE);
+ gle->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T,
+ LOCAL_GL_CLAMP_TO_EDGE);
+ gle->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
+ egl->fDestroyImage(image);
+ }
+
+ const GLenum target = LOCAL_GL_TEXTURE_2D;
+ auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
+ target, tex->name);
+ if (!fb) {
+ return nullptr;
+ }
+
+ return AsUnique(new SharedSurface_AndroidHardwareBuffer(
+ desc, std::move(fb), std::move(tex), buffer));
+}
+
+SharedSurface_AndroidHardwareBuffer::SharedSurface_AndroidHardwareBuffer(
+ const SharedSurfaceDesc& desc, UniquePtr<MozFramebuffer> fb,
+ UniquePtr<Texture> tex, RefPtr<layers::AndroidHardwareBuffer> buffer)
+ : SharedSurface(desc, std::move(fb)),
+ mTex(std::move(tex)),
+ mAndroidHardwareBuffer(buffer) {}
+
+SharedSurface_AndroidHardwareBuffer::~SharedSurface_AndroidHardwareBuffer() {
+ const auto& gl = mDesc.gl;
+ if (!gl || !gl->MakeCurrent()) {
+ return;
+ }
+ const auto& gle = GLContextEGL::Cast(gl);
+ const auto& egl = gle->mEgl;
+
+ if (mSync) {
+ egl->fDestroySync(mSync);
+ mSync = 0;
+ }
+}
+
+void SharedSurface_AndroidHardwareBuffer::ProducerReleaseImpl() {
+ const auto& gl = mDesc.gl;
+ if (!gl || !gl->MakeCurrent()) {
+ return;
+ }
+ const auto& gle = GLContextEGL::Cast(gl);
+ const auto& egl = gle->mEgl;
+
+ if (mSync) {
+ MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
+ mSync = 0;
+ }
+
+ mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+ MOZ_ASSERT(mSync);
+ int rawFd = egl->fDupNativeFenceFDANDROID(mSync);
+ if (rawFd >= 0) {
+ auto fenceFd = ipc::FileDescriptor(UniqueFileHandle(rawFd));
+ mAndroidHardwareBuffer->SetAcquireFence(std::move(fenceFd));
+ }
+
+ gl->fFlush();
+}
+
+Maybe<layers::SurfaceDescriptor>
+SharedSurface_AndroidHardwareBuffer::ToSurfaceDescriptor() {
+ return Some(layers::SurfaceDescriptorAndroidHardwareBuffer(
+ mAndroidHardwareBuffer->mId, mAndroidHardwareBuffer->mSize,
+ mAndroidHardwareBuffer->mFormat));
+}
+
+void SharedSurface_AndroidHardwareBuffer::WaitForBufferOwnership() {
+ ipc::FileDescriptor fenceFd =
+ mAndroidHardwareBuffer->GetAndResetReleaseFence();
+ if (!fenceFd.IsValid()) {
+ return;
+ }
+
+ const auto& gle = GLContextEGL::Cast(mDesc.gl);
+ const auto& egl = gle->mEgl;
+
+ auto rawFD = fenceFd.TakePlatformHandle();
+ const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, rawFD.get(),
+ LOCAL_EGL_NONE};
+
+ EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+ if (!sync) {
+ gfxCriticalNote << "Failed to create EGLSync from fd";
+ return;
+ }
+ // Release fd here, since it is owned by EGLSync
+ Unused << rawFD.release();
+
+ egl->fClientWaitSync(sync, 0, LOCAL_EGL_FOREVER);
+ egl->fDestroySync(sync);
+}
+
+/*static*/
+UniquePtr<SurfaceFactory_AndroidHardwareBuffer>
+SurfaceFactory_AndroidHardwareBuffer::Create(GLContext& gl) {
+ const auto partialDesc = PartialSharedSurfaceDesc{
+ &gl,
+ SharedSurfaceType::AndroidHardwareBuffer,
+ layers::TextureType::AndroidHardwareBuffer,
+ true,
+ };
+ return AsUnique(new SurfaceFactory_AndroidHardwareBuffer(partialDesc));
+}
+
+} // namespace gl
+
+} /* namespace mozilla */
diff --git a/gfx/gl/SharedSurfaceAndroidHardwareBuffer.h b/gfx/gl/SharedSurfaceAndroidHardwareBuffer.h
new file mode 100644
index 0000000000..ef40ad622d
--- /dev/null
+++ b/gfx/gl/SharedSurfaceAndroidHardwareBuffer.h
@@ -0,0 +1,70 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_
+#define SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
+#include "CompositorTypes.h"
+#include "SharedSurface.h"
+
+namespace mozilla {
+
+namespace layers {
+class AndroidHardwareBuffer;
+} // namespace layers
+
+namespace gl {
+
+class SharedSurface_AndroidHardwareBuffer final : public SharedSurface {
+ public:
+ const UniquePtr<Texture> mTex;
+ const RefPtr<layers::AndroidHardwareBuffer> mAndroidHardwareBuffer;
+ EGLSync mSync = 0;
+
+ static UniquePtr<SharedSurface_AndroidHardwareBuffer> Create(
+ const SharedSurfaceDesc&);
+
+ protected:
+ SharedSurface_AndroidHardwareBuffer(
+ const SharedSurfaceDesc&, UniquePtr<MozFramebuffer>, UniquePtr<Texture>,
+ RefPtr<layers::AndroidHardwareBuffer> buffer);
+
+ public:
+ virtual ~SharedSurface_AndroidHardwareBuffer();
+
+ void LockProdImpl() override {}
+ void UnlockProdImpl() override {}
+
+ void ProducerAcquireImpl() override {}
+ void ProducerReleaseImpl() override;
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+
+ void WaitForBufferOwnership() override;
+};
+
+class SurfaceFactory_AndroidHardwareBuffer final : public SurfaceFactory {
+ public:
+ static UniquePtr<SurfaceFactory_AndroidHardwareBuffer> Create(GLContext&);
+
+ private:
+ explicit SurfaceFactory_AndroidHardwareBuffer(
+ const PartialSharedSurfaceDesc& desc)
+ : SurfaceFactory(desc) {}
+
+ public:
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_AndroidHardwareBuffer::Create(desc);
+ }
+};
+
+} // namespace gl
+
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_ANDROID_HARDWARE_BUFFER_H_ */
diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp
new file mode 100644
index 0000000000..4248bdf23d
--- /dev/null
+++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp
@@ -0,0 +1,489 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceD3D11Interop.h"
+
+#include <d3d11.h>
+#include <d3d11_1.h>
+#include "GLContext.h"
+#include "GLBlitHelper.h"
+#include "MozFramebuffer.h"
+#include "ScopedGLHelpers.h"
+#include "WGLLibrary.h"
+#include "nsPrintfCString.h"
+#include "mozilla/gfx/DeviceManagerDx.h"
+#include "mozilla/gfx/FileHandleWrapper.h"
+#include "mozilla/gfx/Logging.h"
+#include "mozilla/layers/LayersSurfaces.h"
+#include "mozilla/StaticPrefs_webgl.h"
+
+namespace mozilla {
+namespace gl {
+
+/*
+Sample Code for WGL_NV_DX_interop2:
+Example: Render to Direct3D 11 backbuffer with openGL:
+
+// create D3D11 device, context and swap chain.
+ID3D11Device *device;
+ID3D11DeviceContext *devCtx;
+IDXGISwapChain *swapChain;
+
+DXGI_SWAP_CHAIN_DESC scd;
+
+<set appropriate swap chain parameters in scd>
+
+hr = D3D11CreateDeviceAndSwapChain(
+ NULL, // pAdapter
+ D3D_DRIVER_TYPE_HARDWARE, // DriverType
+ NULL, // Software
+ 0, // Flags (Do not set
+ // D3D11_CREATE_DEVICE_SINGLETHREADED)
+ NULL, // pFeatureLevels
+ 0, // FeatureLevels
+ D3D11_SDK_VERSION, // SDKVersion
+ &scd, // pSwapChainDesc
+ &swapChain, // ppSwapChain
+ &device, // ppDevice
+ NULL, // pFeatureLevel
+ &devCtx); // ppImmediateContext
+
+// Fetch the swapchain backbuffer
+ID3D11Texture2D *dxColorbuffer;
+swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)&dxColorbuffer);
+
+// Create depth stencil texture
+ID3D11Texture2D *dxDepthBuffer;
+D3D11_TEXTURE2D_DESC depthDesc;
+depthDesc.Usage = D3D11_USAGE_DEFAULT;
+<set other depthDesc parameters appropriately>
+
+// Create Views
+ID3D11RenderTargetView *colorBufferView;
+D3D11_RENDER_TARGET_VIEW_DESC rtd;
+<set rtd parameters appropriately>
+device->CreateRenderTargetView(dxColorbuffer, &rtd, &colorBufferView);
+
+ID3D11DepthStencilView *depthBufferView;
+D3D11_DEPTH_STENCIL_VIEW_DESC dsd;
+<set dsd parameters appropriately>
+device->CreateDepthStencilView(dxDepthBuffer, &dsd, &depthBufferView);
+
+// Attach back buffer and depth texture to redertarget for the device.
+devCtx->OMSetRenderTargets(1, &colorBufferView, depthBufferView);
+
+// Register D3D11 device with GL
+HANDLE gl_handleD3D;
+gl_handleD3D = wglDXOpenDeviceNV(device);
+
+// register the Direct3D color and depth/stencil buffers as
+// renderbuffers in opengl
+GLuint gl_names[2];
+HANDLE gl_handles[2];
+
+glGenRenderbuffers(2, gl_names);
+
+gl_handles[0] = wglDXRegisterObjectNV(gl_handleD3D, dxColorBuffer,
+ gl_names[0],
+ GL_RENDERBUFFER,
+ WGL_ACCESS_READ_WRITE_NV);
+
+gl_handles[1] = wglDXRegisterObjectNV(gl_handleD3D, dxDepthBuffer,
+ gl_names[1],
+ GL_RENDERBUFFER,
+ WGL_ACCESS_READ_WRITE_NV);
+
+// attach the Direct3D buffers to an FBO
+glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, gl_names[0]);
+glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, gl_names[1]);
+glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, gl_names[1]);
+
+while (!done) {
+ <direct3d renders to the render targets>
+
+ // lock the render targets for GL access
+ wglDXLockObjectsNVX(gl_handleD3D, 2, gl_handles);
+
+ <opengl renders to the render targets>
+
+ // unlock the render targets
+ wglDXUnlockObjectsNVX(gl_handleD3D, 2, gl_handles);
+
+ <direct3d renders to the render targets and presents
+ the results on the screen>
+}
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+// DXInterop2Device
+
+class ScopedContextState final {
+ ID3D11DeviceContext1* const mD3DContext;
+ RefPtr<ID3DDeviceContextState> mOldContextState;
+
+ public:
+ ScopedContextState(ID3D11DeviceContext1* d3dContext,
+ ID3DDeviceContextState* newContextState)
+ : mD3DContext(d3dContext), mOldContextState(nullptr) {
+ if (!mD3DContext) return;
+
+ mD3DContext->SwapDeviceContextState(newContextState,
+ getter_AddRefs(mOldContextState));
+ }
+
+ ~ScopedContextState() {
+ if (!mD3DContext) return;
+
+ mD3DContext->SwapDeviceContextState(mOldContextState, nullptr);
+ }
+};
+
+class DXInterop2Device : public RefCounted<DXInterop2Device> {
+ public:
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(DXInterop2Device)
+
+ WGLLibrary* const mWGL;
+ const RefPtr<ID3D11Device> mD3D; // Only needed for lifetime guarantee.
+ const HANDLE mInteropDevice;
+ GLContext* const mGL;
+
+ // AMD workaround.
+ const RefPtr<ID3D11DeviceContext1> mD3DContext;
+ const RefPtr<ID3DDeviceContextState> mContextState;
+
+ static already_AddRefed<DXInterop2Device> Open(WGLLibrary* wgl,
+ GLContext* gl) {
+ MOZ_ASSERT(wgl->HasDXInterop2());
+
+ const RefPtr<ID3D11Device> d3d =
+ gfx::DeviceManagerDx::Get()->GetContentDevice();
+ if (!d3d) {
+ gfxCriticalNote
+ << "DXInterop2Device::Open: Failed to create D3D11 device.";
+ return nullptr;
+ }
+
+ if (!gl->MakeCurrent()) return nullptr;
+
+ RefPtr<ID3D11DeviceContext1> d3dContext;
+ RefPtr<ID3DDeviceContextState> contextState;
+ if (gl->WorkAroundDriverBugs() && gl->Vendor() == GLVendor::ATI) {
+ // AMD calls ID3D10Device::Flush, so we need to be in ID3D10Device mode.
+ RefPtr<ID3D11Device1> d3d11_1;
+ auto hr =
+ d3d->QueryInterface(__uuidof(ID3D11Device1), getter_AddRefs(d3d11_1));
+ if (!SUCCEEDED(hr)) return nullptr;
+
+ d3d11_1->GetImmediateContext1(getter_AddRefs(d3dContext));
+ MOZ_ASSERT(d3dContext);
+
+ const D3D_FEATURE_LEVEL featureLevel10_0 = D3D_FEATURE_LEVEL_10_0;
+ hr = d3d11_1->CreateDeviceContextState(
+ 0, &featureLevel10_0, 1, D3D11_SDK_VERSION, __uuidof(ID3D10Device),
+ nullptr, getter_AddRefs(contextState));
+ if (!SUCCEEDED(hr)) return nullptr;
+ }
+
+ const auto interopDevice = wgl->mSymbols.fDXOpenDeviceNV(d3d);
+ if (!interopDevice) {
+ gfxCriticalNote << "DXInterop2Device::Open: DXOpenDevice failed.";
+ return nullptr;
+ }
+
+ return MakeAndAddRef<DXInterop2Device>(wgl, d3d, interopDevice, gl,
+ d3dContext, contextState);
+ }
+
+ DXInterop2Device(WGLLibrary* wgl, ID3D11Device* d3d, HANDLE interopDevice,
+ GLContext* gl, ID3D11DeviceContext1* d3dContext,
+ ID3DDeviceContextState* contextState)
+ : mWGL(wgl),
+ mD3D(d3d),
+ mInteropDevice(interopDevice),
+ mGL(gl),
+ mD3DContext(d3dContext),
+ mContextState(contextState) {}
+
+ ~DXInterop2Device() {
+ const auto isCurrent = mGL->MakeCurrent();
+
+ if (mWGL->mSymbols.fDXCloseDeviceNV(mInteropDevice)) return;
+
+ if (isCurrent) {
+ // That shouldn't have failed.
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage(
+ "wglDXCloseDevice(0x%p) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ }
+ }
+
+ HANDLE RegisterObject(void* d3dObject, GLuint name, GLenum type,
+ GLenum access) const {
+ if (!mGL->MakeCurrent()) return nullptr;
+
+ const ScopedContextState autoCS(mD3DContext, mContextState);
+ const auto ret = mWGL->mSymbols.fDXRegisterObjectNV(
+ mInteropDevice, d3dObject, name, type, access);
+ if (ret) return ret;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage(
+ "wglDXRegisterObject(0x%p, 0x%p, %u, 0x%04x,"
+ " 0x%04x) failed: GetLastError(): %u\n",
+ mInteropDevice, d3dObject, name, type, access, error);
+ gfxCriticalNote << errorMessage.BeginReading();
+ return nullptr;
+ }
+
+ bool UnregisterObject(HANDLE lockHandle) const {
+ const auto isCurrent = mGL->MakeCurrent();
+
+ const ScopedContextState autoCS(mD3DContext, mContextState);
+ if (mWGL->mSymbols.fDXUnregisterObjectNV(mInteropDevice, lockHandle))
+ return true;
+
+ if (!isCurrent) {
+ // That shouldn't have failed.
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage(
+ "wglDXUnregisterObject(0x%p, 0x%p) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ }
+ return false;
+ }
+
+ bool LockObject(HANDLE lockHandle) const {
+ MOZ_ASSERT(mGL->IsCurrent());
+
+ if (mWGL->mSymbols.fDXLockObjectsNV(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ if (!mGL->MakeCurrent()) return false;
+
+ gfxCriticalNote << "wglDXLockObjects called without mGL being current."
+ << " Retrying after MakeCurrent.";
+
+ if (mWGL->mSymbols.fDXLockObjectsNV(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage(
+ "wglDXLockObjects(0x%p, 1, {0x%p}) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ return false;
+ }
+
+ bool UnlockObject(HANDLE lockHandle) const {
+ MOZ_ASSERT(mGL->IsCurrent());
+
+ if (mWGL->mSymbols.fDXUnlockObjectsNV(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ if (!mGL->MakeCurrent()) return false;
+
+ gfxCriticalNote << "wglDXUnlockObjects called without mGL being current."
+ << " Retrying after MakeCurrent.";
+
+ if (mWGL->mSymbols.fDXUnlockObjectsNV(mInteropDevice, 1, &lockHandle))
+ return true;
+
+ const uint32_t error = GetLastError();
+ const nsPrintfCString errorMessage(
+ "wglDXUnlockObjects(0x%p, 1, {0x%p}) failed:"
+ " GetLastError(): %u\n",
+ mInteropDevice, lockHandle, error);
+ gfxCriticalError() << errorMessage.BeginReading();
+ return false;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Shared Surface
+
+/*static*/
+UniquePtr<SharedSurface_D3D11Interop> SharedSurface_D3D11Interop::Create(
+ const SharedSurfaceDesc& desc, DXInterop2Device* interop) {
+ const auto& gl = desc.gl;
+ const auto& size = desc.size;
+ const auto& d3d = interop->mD3D;
+
+ auto data = Data{interop};
+
+ // Create a texture in case we need to readback.
+ const DXGI_FORMAT format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ CD3D11_TEXTURE2D_DESC texDesc(format, size.width, size.height, 1, 1);
+ texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
+ D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
+
+ auto hr =
+ d3d->CreateTexture2D(&texDesc, nullptr, getter_AddRefs(data.texD3D));
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to create texture for CanvasLayer!");
+ return nullptr;
+ }
+
+ RefPtr<IDXGIResource1> texDXGI;
+ hr = data.texD3D->QueryInterface(__uuidof(IDXGIResource1),
+ getter_AddRefs(texDXGI));
+ if (FAILED(hr)) {
+ NS_WARNING("Failed to open texture for sharing!");
+ return nullptr;
+ }
+
+ HANDLE sharedHandle = nullptr;
+ texDXGI->CreateSharedHandle(
+ nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
+ &sharedHandle);
+
+ data.dxgiHandle = new gfx::FileHandleWrapper(UniqueFileHandle(sharedHandle));
+
+ ////
+
+ if (!gl->MakeCurrent()) {
+ NS_WARNING("MakeCurrent failed.");
+ return nullptr;
+ }
+
+ data.interopRb = MakeUnique<Renderbuffer>(*gl);
+ data.lockHandle = interop->RegisterObject(data.texD3D, data.interopRb->name,
+ LOCAL_GL_RENDERBUFFER,
+ LOCAL_WGL_ACCESS_WRITE_DISCARD_NV);
+ if (!data.lockHandle) {
+ NS_WARNING("Failed to register D3D object with WGL.");
+ return nullptr;
+ }
+
+ auto fbForDrawing = MozFramebuffer::CreateForBacking(
+ gl, size, 0, false, LOCAL_GL_RENDERBUFFER, data.interopRb->name);
+ if (!fbForDrawing) return nullptr;
+
+ // -
+
+ {
+ GLint samples = 0;
+ {
+ const ScopedBindRenderbuffer bindRB(gl, data.interopRb->name);
+ gl->fGetRenderbufferParameteriv(LOCAL_GL_RENDERBUFFER,
+ LOCAL_GL_RENDERBUFFER_SAMPLES, &samples);
+ }
+ if (samples > 0) { // Intel
+ // Intel's dx_interop GL-side textures have SAMPLES=1, likely because
+ // that's what the D3DTextures technically have. However, SAMPLES=1 is
+ // very different from SAMPLES=0 in GL. For more, see
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1325835
+
+ // Our ShSurf tex or rb must be single-sampled.
+ data.interopFbIfNeedsIndirect = std::move(fbForDrawing);
+ fbForDrawing = MozFramebuffer::Create(gl, size, 0, false);
+ }
+ }
+
+ // -
+
+ return AsUnique(new SharedSurface_D3D11Interop(desc, std::move(fbForDrawing),
+ std::move(data)));
+}
+
+SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(
+ const SharedSurfaceDesc& desc, UniquePtr<MozFramebuffer>&& fbForDrawing,
+ Data&& data)
+ : SharedSurface(desc, std::move(fbForDrawing)),
+ mData(std::move(data)),
+ mNeedsFinish(StaticPrefs::webgl_dxgl_needs_finish()) {}
+
+SharedSurface_D3D11Interop::~SharedSurface_D3D11Interop() {
+ MOZ_ASSERT(!IsProducerAcquired());
+
+ const auto& gl = mDesc.gl;
+ if (!gl || !gl->MakeCurrent()) return;
+
+ if (!mData.interop->UnregisterObject(mData.lockHandle)) {
+ NS_WARNING("Failed to release mLockHandle, possibly leaking it.");
+ }
+}
+
+void SharedSurface_D3D11Interop::ProducerAcquireImpl() {
+ MOZ_ASSERT(!mLockedForGL);
+
+ // Now we have the mutex, we can lock for GL.
+ MOZ_ALWAYS_TRUE(mData.interop->LockObject(mData.lockHandle));
+
+ mLockedForGL = true;
+}
+
+void SharedSurface_D3D11Interop::ProducerReleaseImpl() {
+ const auto& gl = mDesc.gl;
+ MOZ_ASSERT(mLockedForGL);
+
+ if (mData.interopFbIfNeedsIndirect) {
+ const ScopedBindFramebuffer bindFB(gl, mData.interopFbIfNeedsIndirect->mFB);
+ gl->BlitHelper()->DrawBlitTextureToFramebuffer(mFb->ColorTex(), mDesc.size,
+ mDesc.size);
+ }
+
+ if (mNeedsFinish) {
+ gl->fFinish();
+ } else {
+ // We probably don't even need this.
+ gl->fFlush();
+ }
+ MOZ_ALWAYS_TRUE(mData.interop->UnlockObject(mData.lockHandle));
+
+ mLockedForGL = false;
+}
+
+Maybe<layers::SurfaceDescriptor>
+SharedSurface_D3D11Interop::ToSurfaceDescriptor() {
+ const auto format = gfx::SurfaceFormat::B8G8R8A8;
+ return Some(layers::SurfaceDescriptorD3D10(
+ mData.dxgiHandle, /* gpuProcessTextureId */ Nothing(),
+ /* arrayIndex */ 0, format, mDesc.size, mDesc.colorSpace,
+ gfx::ColorRange::FULL, /* hasKeyedMutex */ true,
+ /* fenceInfo */ Nothing(), /* gpuProcessQueryId */ Nothing()));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Factory
+
+/*static*/
+UniquePtr<SurfaceFactory_D3D11Interop> SurfaceFactory_D3D11Interop::Create(
+ GLContext& gl) {
+ WGLLibrary* wgl = &sWGLLib;
+ if (!wgl || !wgl->HasDXInterop2()) return nullptr;
+
+ if (XRE_IsContentProcess()) {
+ gfxPlatform::GetPlatform()->EnsureDevicesInitialized();
+ }
+
+ const RefPtr<DXInterop2Device> interop = DXInterop2Device::Open(wgl, &gl);
+ if (!interop) {
+ NS_WARNING("Failed to open D3D device for use by WGL.");
+ return nullptr;
+ }
+
+ return AsUnique(new SurfaceFactory_D3D11Interop(
+ {&gl, SharedSurfaceType::DXGLInterop2, layers::TextureType::D3D11, true},
+ interop));
+}
+
+SurfaceFactory_D3D11Interop::SurfaceFactory_D3D11Interop(
+ const PartialSharedSurfaceDesc& desc, DXInterop2Device* interop)
+ : SurfaceFactory(desc), mInterop(interop) {}
+
+SurfaceFactory_D3D11Interop::~SurfaceFactory_D3D11Interop() = default;
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h
new file mode 100644
index 0000000000..960850c27e
--- /dev/null
+++ b/gfx/gl/SharedSurfaceD3D11Interop.h
@@ -0,0 +1,84 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_D3D11_INTEROP_H_
+#define SHARED_SURFACE_D3D11_INTEROP_H_
+
+#include <d3d11.h>
+#include <windows.h>
+#include "SharedSurface.h"
+
+namespace mozilla {
+
+namespace gfx {
+class FileHandleWrapper;
+} // namespace gfx
+
+namespace gl {
+
+class DXInterop2Device;
+class GLContext;
+class WGLLibrary;
+
+class SharedSurface_D3D11Interop final : public SharedSurface {
+ public:
+ struct Data final {
+ const RefPtr<DXInterop2Device> interop;
+ HANDLE lockHandle;
+ RefPtr<ID3D11Texture2D> texD3D;
+ RefPtr<gfx::FileHandleWrapper> dxgiHandle;
+ UniquePtr<Renderbuffer> interopRb;
+ UniquePtr<MozFramebuffer> interopFbIfNeedsIndirect;
+ };
+ const Data mData;
+ const bool mNeedsFinish;
+
+ private:
+ bool mLockedForGL = false;
+
+ public:
+ static UniquePtr<SharedSurface_D3D11Interop> Create(const SharedSurfaceDesc&,
+ DXInterop2Device*);
+
+ private:
+ SharedSurface_D3D11Interop(const SharedSurfaceDesc&,
+ UniquePtr<MozFramebuffer>&& fbForDrawing, Data&&);
+
+ public:
+ virtual ~SharedSurface_D3D11Interop();
+
+ void LockProdImpl() override {}
+ void UnlockProdImpl() override {}
+
+ void ProducerAcquireImpl() override;
+ void ProducerReleaseImpl() override;
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+};
+
+class SurfaceFactory_D3D11Interop : public SurfaceFactory {
+ public:
+ const RefPtr<DXInterop2Device> mInterop;
+
+ static UniquePtr<SurfaceFactory_D3D11Interop> Create(GLContext& gl);
+
+ protected:
+ SurfaceFactory_D3D11Interop(const PartialSharedSurfaceDesc&,
+ DXInterop2Device* interop);
+
+ public:
+ virtual ~SurfaceFactory_D3D11Interop();
+
+ protected:
+ UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_D3D11Interop::Create(desc, mInterop);
+ }
+};
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_D3D11_INTEROP_H_ */
diff --git a/gfx/gl/SharedSurfaceDMABUF.cpp b/gfx/gl/SharedSurfaceDMABUF.cpp
new file mode 100644
index 0000000000..56315bb317
--- /dev/null
+++ b/gfx/gl/SharedSurfaceDMABUF.cpp
@@ -0,0 +1,142 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceDMABUF.h"
+
+#include "gfxPlatform.h"
+#include "GLContextEGL.h"
+#include "MozFramebuffer.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+#include "mozilla/gfx/gfxVars.h"
+#include "mozilla/widget/DMABufLibWrapper.h"
+
+namespace mozilla::gl {
+
+static bool HasDmaBufExtensions(const GLContextEGL* gl) {
+ const auto& egl = *(gl->mEgl);
+ return egl.IsExtensionSupported(EGLExtension::EXT_image_dma_buf_import) &&
+ egl.IsExtensionSupported(
+ EGLExtension::EXT_image_dma_buf_import_modifiers) &&
+ egl.IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export);
+}
+
+/*static*/
+UniquePtr<SharedSurface_DMABUF> SharedSurface_DMABUF::Create(
+ const SharedSurfaceDesc& desc) {
+ const auto& gle = GLContextEGL::Cast(desc.gl);
+ const auto& context = gle->mContext;
+ const auto& egl = *(gle->mEgl);
+
+ RefPtr<DMABufSurface> surface;
+ UniquePtr<MozFramebuffer> fb;
+
+ if (!HasDmaBufExtensions(gle) || !gfx::gfxVars::UseDMABufSurfaceExport()) {
+ // Using MESA_image_dma_buf_export is not supported or it's broken.
+ // Create dmabuf surface directly via GBM and create
+ // EGLImage/framebuffer over it.
+ const auto flags = static_cast<DMABufSurfaceFlags>(
+ DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
+ surface = DMABufSurfaceRGBA::CreateDMABufSurface(desc.size.width,
+ desc.size.height, flags);
+ if (!surface || !surface->CreateTexture(desc.gl)) {
+ return nullptr;
+ }
+ const auto tex = surface->GetTexture();
+ fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
+ LOCAL_GL_TEXTURE_2D, tex);
+ if (!fb) return nullptr;
+ } else {
+ // Use MESA_image_dma_buf_export to create EGLImage/framebuffer directly
+ // and derive dmabuf from it.
+ fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
+ if (!fb) return nullptr;
+
+ const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
+ const auto image =
+ egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
+ if (!image) return nullptr;
+
+ surface = DMABufSurfaceRGBA::CreateDMABufSurface(
+ desc.gl, image, desc.size.width, desc.size.height);
+ if (!surface) return nullptr;
+ }
+ return AsUnique(new SharedSurface_DMABUF(desc, std::move(fb), surface));
+}
+
+SharedSurface_DMABUF::SharedSurface_DMABUF(const SharedSurfaceDesc& desc,
+ UniquePtr<MozFramebuffer> fb,
+ const RefPtr<DMABufSurface> surface)
+ : SharedSurface(desc, std::move(fb)), mSurface(surface) {}
+
+SharedSurface_DMABUF::~SharedSurface_DMABUF() {
+ const auto& gl = mDesc.gl;
+ if (!gl || !gl->MakeCurrent()) {
+ return;
+ }
+ mSurface->ReleaseTextures();
+}
+
+void SharedSurface_DMABUF::ProducerReleaseImpl() { mSurface->FenceSet(); }
+
+void SharedSurface_DMABUF::WaitForBufferOwnership() { mSurface->FenceWait(); }
+
+Maybe<layers::SurfaceDescriptor> SharedSurface_DMABUF::ToSurfaceDescriptor() {
+ layers::SurfaceDescriptor desc;
+ if (!mSurface->Serialize(desc)) return {};
+ return Some(desc);
+}
+
+/*static*/
+UniquePtr<SurfaceFactory_DMABUF> SurfaceFactory_DMABUF::Create(GLContext& gl) {
+ if (!widget::DMABufDevice::IsDMABufWebGLEnabled()) {
+ return nullptr;
+ }
+
+ auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
+ if (dmabufFactory->CanCreateSurface(gl)) {
+ return dmabufFactory;
+ }
+
+ LOGDMABUF(
+ ("SurfaceFactory_DMABUF::Create() failed, fallback to SW buffers.\n"));
+ widget::DMABufDevice::DisableDMABufWebGL();
+ return nullptr;
+}
+
+bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
+ UniquePtr<SharedSurface> test =
+ CreateShared(gfx::IntSize(1, 1), gfx::ColorSpace2::SRGB);
+ if (!test) {
+ LOGDMABUF((
+ "SurfaceFactory_DMABUF::CanCreateSurface() failed to create surface."));
+ return false;
+ }
+ auto desc = test->ToSurfaceDescriptor();
+ if (!desc) {
+ LOGDMABUF(
+ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to serialize "
+ "surface."));
+ return false;
+ }
+ RefPtr<DMABufSurface> importedSurface =
+ DMABufSurface::CreateDMABufSurface(*desc);
+ if (!importedSurface) {
+ LOGDMABUF((
+ "SurfaceFactory_DMABUF::CanCreateSurface() failed to import surface."));
+ return false;
+ }
+ if (!importedSurface->CreateTexture(&gl)) {
+ LOGDMABUF(
+ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to create texture "
+ "over surface."));
+ return false;
+ }
+ return true;
+}
+
+SurfaceFactory_DMABUF::SurfaceFactory_DMABUF(GLContext& gl)
+ : SurfaceFactory({&gl, SharedSurfaceType::EGLSurfaceDMABUF,
+ layers::TextureType::DMABUF, true}) {}
+} // namespace mozilla::gl
diff --git a/gfx/gl/SharedSurfaceDMABUF.h b/gfx/gl/SharedSurfaceDMABUF.h
new file mode 100644
index 0000000000..6aaa4d333e
--- /dev/null
+++ b/gfx/gl/SharedSurfaceDMABUF.h
@@ -0,0 +1,69 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_DMABUF_H_
+#define SHARED_SURFACE_DMABUF_H_
+
+#include "SharedSurface.h"
+#include "mozilla/widget/DMABufSurface.h"
+
+namespace mozilla {
+namespace gl {
+
+class GLContext;
+class GLLibraryEGL;
+
+class SharedSurface_DMABUF final : public SharedSurface {
+ public:
+ const RefPtr<DMABufSurface> mSurface;
+
+ static UniquePtr<SharedSurface_DMABUF> Create(const SharedSurfaceDesc&);
+
+ private:
+ SharedSurface_DMABUF(const SharedSurfaceDesc&, UniquePtr<MozFramebuffer>,
+ RefPtr<DMABufSurface>);
+
+ void UpdateProdTexture(const MutexAutoLock& curAutoLock);
+
+ public:
+ virtual ~SharedSurface_DMABUF();
+
+ // Exclusive Content/WebGL lock/unlock of surface for write
+ virtual void LockProdImpl() override {}
+ virtual void UnlockProdImpl() override {}
+
+ // Non-exclusive Content/WebGL lock/unlock of surface for write
+ virtual void ProducerAcquireImpl() override {}
+ virtual void ProducerReleaseImpl() override;
+
+ // Non-exclusive Content/WebGL lock/unlock for read from surface
+ virtual void ProducerReadAcquireImpl() override {}
+ virtual void ProducerReadReleaseImpl() override {}
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+
+ void WaitForBufferOwnership() override;
+};
+
+class SurfaceFactory_DMABUF : public SurfaceFactory {
+ public:
+ static UniquePtr<SurfaceFactory_DMABUF> Create(GLContext& gl);
+
+ explicit SurfaceFactory_DMABUF(GLContext&);
+
+ public:
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_DMABUF::Create(desc);
+ }
+
+ bool CanCreateSurface(GLContext& gl);
+};
+
+} // namespace gl
+
+} // namespace mozilla
+
+#endif /* SHARED_SURFACE_DMABUF_H_ */
diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp
new file mode 100644
index 0000000000..74dd695393
--- /dev/null
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -0,0 +1,269 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceEGL.h"
+
+#include "GLBlitHelper.h"
+#include "GLContextEGL.h"
+#include "GLContextProvider.h"
+#include "GLLibraryEGL.h"
+#include "GLReadTexImageHelper.h"
+#include "MozFramebuffer.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+#include "SharedSurface.h"
+
+#if defined(MOZ_WIDGET_ANDROID)
+# include "AndroidNativeWindow.h"
+# include "mozilla/java/SurfaceAllocatorWrappers.h"
+# include "mozilla/java/GeckoSurfaceTextureWrappers.h"
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+namespace mozilla {
+namespace gl {
+
+static bool HasEglImageExtensions(const GLContextEGL& gl) {
+ const auto& egl = *(gl.mEgl);
+ return egl.HasKHRImageBase() &&
+ egl.IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
+ (gl.IsExtensionSupported(GLContext::OES_EGL_image_external) ||
+ gl.IsExtensionSupported(GLContext::OES_EGL_image));
+}
+
+/*static*/
+UniquePtr<SurfaceFactory_EGLImage> SurfaceFactory_EGLImage::Create(
+ GLContext& gl_) {
+ auto& gl = *GLContextEGL::Cast(&gl_);
+ if (!HasEglImageExtensions(gl)) return nullptr;
+
+ const auto partialDesc = PartialSharedSurfaceDesc{
+ &gl, SharedSurfaceType::EGLImageShare, layers::TextureType::EGLImage,
+ false, // Can't recycle, as mSync changes never update TextureHost.
+ };
+ return AsUnique(new SurfaceFactory_EGLImage(partialDesc));
+}
+
+// -
+
+/*static*/
+UniquePtr<SharedSurface_EGLImage> SharedSurface_EGLImage::Create(
+ const SharedSurfaceDesc& desc) {
+ const auto& gle = GLContextEGL::Cast(desc.gl);
+ const auto& context = gle->mContext;
+ const auto& egl = *(gle->mEgl);
+
+ auto fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
+ if (!fb) return nullptr;
+
+ const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
+ const auto image =
+ egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
+ if (!image) return nullptr;
+
+ return AsUnique(new SharedSurface_EGLImage(desc, std::move(fb), image));
+}
+
+SharedSurface_EGLImage::SharedSurface_EGLImage(const SharedSurfaceDesc& desc,
+ UniquePtr<MozFramebuffer>&& fb,
+ const EGLImage image)
+ : SharedSurface(desc, std::move(fb)),
+ mMutex("SharedSurface_EGLImage mutex"),
+ mImage(image) {}
+
+SharedSurface_EGLImage::~SharedSurface_EGLImage() {
+ const auto& gle = GLContextEGL::Cast(mDesc.gl);
+ const auto& egl = gle->mEgl;
+ egl->fDestroyImage(mImage);
+
+ if (mSync) {
+ // We can't call this unless we have the ext, but we will always have
+ // the ext if we have something to destroy.
+ egl->fDestroySync(mSync);
+ mSync = 0;
+ }
+}
+
+void SharedSurface_EGLImage::ProducerReleaseImpl() {
+ const auto& gl = GLContextEGL::Cast(mDesc.gl);
+ const auto& egl = gl->mEgl;
+
+ MutexAutoLock lock(mMutex);
+ gl->MakeCurrent();
+
+ if (egl->IsExtensionSupported(EGLExtension::KHR_fence_sync) &&
+ gl->IsExtensionSupported(GLContext::OES_EGL_sync)) {
+ if (mSync) {
+ MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice.");
+ MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
+ mSync = 0;
+ }
+
+ mSync = egl->fCreateSync(LOCAL_EGL_SYNC_FENCE, nullptr);
+ if (mSync) {
+ gl->fFlush();
+ return;
+ }
+ }
+
+ MOZ_ASSERT(!mSync);
+ gl->fFinish();
+}
+
+void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
+ const auto& gle = GLContextEGL::Cast(mDesc.gl);
+ const auto& egl = gle->mEgl;
+ // Wait on the fence, because presumably we're going to want to read this
+ // surface
+ if (mSync) {
+ egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
+ }
+}
+
+Maybe<layers::SurfaceDescriptor> SharedSurface_EGLImage::ToSurfaceDescriptor() {
+ return Some(layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync,
+ mDesc.size, true));
+}
+
+////////////////////////////////////////////////////////////////////////
+
+#ifdef MOZ_WIDGET_ANDROID
+
+/*static*/
+UniquePtr<SharedSurface_SurfaceTexture> SharedSurface_SurfaceTexture::Create(
+ const SharedSurfaceDesc& desc) {
+ const auto& size = desc.size;
+
+ jni::Object::LocalRef surfaceObj;
+ const bool useSingleBuffer =
+ desc.gl->Renderer() != GLRenderer::AndroidEmulator;
+
+ if (useSingleBuffer) {
+ surfaceObj =
+ java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
+ }
+
+ if (!surfaceObj) {
+ // Try multi-buffer mode
+ surfaceObj =
+ java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
+ }
+
+ if (!surfaceObj) {
+ // Give up
+ NS_WARNING("Failed to allocate SurfaceTexture!");
+ return nullptr;
+ }
+ const auto surface = java::GeckoSurface::Ref::From(surfaceObj);
+
+ AndroidNativeWindow window(surface);
+ const auto& gle = GLContextEGL::Cast(desc.gl);
+ MOZ_ASSERT(gle);
+ const auto eglSurface = gle->CreateCompatibleSurface(window.NativeWindow());
+ if (!eglSurface) return nullptr;
+
+ return AsUnique(new SharedSurface_SurfaceTexture(desc, surface, eglSurface));
+}
+
+SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(
+ const SharedSurfaceDesc& desc, java::GeckoSurface::Param surface,
+ const EGLSurface eglSurface)
+ : SharedSurface(desc, nullptr),
+ mSurface(surface),
+ mEglSurface(eglSurface),
+ mEglDisplay(GLContextEGL::Cast(desc.gl)->mEgl) {}
+
+SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
+ if (mOrigEglSurface) {
+ // We are about to destroy mEglSurface.
+ // Make sure gl->SetEGLSurfaceOverride() doesn't keep a reference
+ // to the surface.
+ UnlockProd();
+ }
+
+ std::shared_ptr<EglDisplay> display = mEglDisplay.lock();
+ if (display) {
+ display->fDestroySurface(mEglSurface);
+ }
+ java::SurfaceAllocator::DisposeSurface(mSurface);
+}
+
+void SharedSurface_SurfaceTexture::LockProdImpl() {
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
+ mOrigEglSurface = gl->GetEGLSurfaceOverride();
+ gl->SetEGLSurfaceOverride(mEglSurface);
+}
+
+void SharedSurface_SurfaceTexture::UnlockProdImpl() {
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ GLContextEGL* gl = GLContextEGL::Cast(mDesc.gl);
+ MOZ_ASSERT(gl->GetEGLSurfaceOverride() == mEglSurface);
+
+ gl->SetEGLSurfaceOverride(mOrigEglSurface);
+ mOrigEglSurface = nullptr;
+}
+
+void SharedSurface_SurfaceTexture::ProducerReadReleaseImpl() {
+ // This GeckoSurfaceTexture is not SurfaceTexture of this class's GeckoSurface
+ // when current process is content process. In this case, SurfaceTexture of
+ // this class's GeckoSurface does not exist in this process. It exists in
+ // compositor's process. Then GeckoSurfaceTexture in this process is a sync
+ // surface that copies back the SurfaceTextrure from compositor's process. It
+ // was added by Bug 1486659. Then SurfaceTexture::UpdateTexImage() becomes
+ // very heavy weight, since it does copy back the SurfaceTextrure from
+ // compositor's process.
+ java::GeckoSurfaceTexture::LocalRef surfaceTexture =
+ java::GeckoSurfaceTexture::Lookup(mSurface->GetHandle());
+ if (!surfaceTexture) {
+ NS_ERROR("Didn't find GeckoSurfaceTexture in ProducerReadReleaseImpl");
+ return;
+ }
+ surfaceTexture->UpdateTexImage();
+ // Non single buffer mode Surface does not need ReleaseTexImage() call.
+ // When SurfaceTexture is sync Surface, it might not be single buffer mode.
+ if (surfaceTexture->IsSingleBuffer()) {
+ surfaceTexture->ReleaseTexImage();
+ }
+}
+
+void SharedSurface_SurfaceTexture::Commit() {
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ LockProdImpl();
+ mDesc.gl->SwapBuffers();
+ UnlockProdImpl();
+ mSurface->SetAvailable(false);
+}
+
+void SharedSurface_SurfaceTexture::WaitForBufferOwnership() {
+ mSurface->SetAvailable(true);
+}
+
+bool SharedSurface_SurfaceTexture::IsBufferAvailable() const {
+ return mSurface->GetAvailable();
+}
+
+bool SharedSurface_SurfaceTexture::IsValid() const {
+ return !mSurface->IsReleased();
+}
+
+Maybe<layers::SurfaceDescriptor>
+SharedSurface_SurfaceTexture::ToSurfaceDescriptor() {
+ return Some(layers::SurfaceTextureDescriptor(
+ mSurface->GetHandle(), mDesc.size, gfx::SurfaceFormat::R8G8B8A8,
+ false /* Do NOT override colorspace */, false /* NOT continuous */,
+ Nothing() /* Do not override transform */));
+}
+
+SurfaceFactory_SurfaceTexture::SurfaceFactory_SurfaceTexture(GLContext& gl)
+ : SurfaceFactory({&gl, SharedSurfaceType::AndroidSurfaceTexture,
+ layers::TextureType::AndroidNativeWindow, true}) {}
+
+#endif // MOZ_WIDGET_ANDROID
+
+} // namespace gl
+
+} /* namespace mozilla */
diff --git a/gfx/gl/SharedSurfaceEGL.h b/gfx/gl/SharedSurfaceEGL.h
new file mode 100644
index 0000000000..569421f945
--- /dev/null
+++ b/gfx/gl/SharedSurfaceEGL.h
@@ -0,0 +1,130 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_EGL_H_
+#define SHARED_SURFACE_EGL_H_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
+#include "CompositorTypes.h"
+#include "SharedSurface.h"
+
+#ifdef MOZ_WIDGET_ANDROID
+# include "AndroidNativeWindow.h"
+# include "GLLibraryEGL.h"
+#endif
+
+namespace mozilla {
+namespace gl {
+
+class GLLibraryEGL;
+
+// -
+// EGLImage
+
+class SharedSurface_EGLImage final : public SharedSurface {
+ mutable Mutex mMutex MOZ_UNANNOTATED;
+ EGLSync mSync = 0;
+
+ public:
+ const EGLImage mImage;
+
+ static UniquePtr<SharedSurface_EGLImage> Create(const SharedSurfaceDesc&);
+
+ protected:
+ SharedSurface_EGLImage(const SharedSurfaceDesc&,
+ UniquePtr<MozFramebuffer>&& fb, EGLImage);
+
+ void UpdateProdTexture(const MutexAutoLock& curAutoLock);
+
+ public:
+ virtual ~SharedSurface_EGLImage();
+
+ virtual void LockProdImpl() override {}
+ virtual void UnlockProdImpl() override {}
+
+ virtual void ProducerAcquireImpl() override {}
+ virtual void ProducerReleaseImpl() override;
+
+ virtual void ProducerReadAcquireImpl() override;
+ virtual void ProducerReadReleaseImpl() override{};
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+};
+
+class SurfaceFactory_EGLImage final : public SurfaceFactory {
+ public:
+ static UniquePtr<SurfaceFactory_EGLImage> Create(GLContext&);
+
+ private:
+ explicit SurfaceFactory_EGLImage(const PartialSharedSurfaceDesc& desc)
+ : SurfaceFactory(desc) {}
+
+ public:
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_EGLImage::Create(desc);
+ }
+};
+
+// -
+// SurfaceTexture
+
+#ifdef MOZ_WIDGET_ANDROID
+
+class SharedSurface_SurfaceTexture final : public SharedSurface {
+ const java::GeckoSurface::GlobalRef mSurface;
+ const EGLSurface mEglSurface;
+ const std::weak_ptr<EglDisplay> mEglDisplay;
+ EGLSurface mOrigEglSurface = 0;
+
+ public:
+ static UniquePtr<SharedSurface_SurfaceTexture> Create(
+ const SharedSurfaceDesc&);
+
+ java::GeckoSurface::Param JavaSurface() { return mSurface; }
+
+ protected:
+ SharedSurface_SurfaceTexture(const SharedSurfaceDesc&,
+ java::GeckoSurface::Param surface, EGLSurface);
+
+ public:
+ virtual ~SharedSurface_SurfaceTexture();
+
+ virtual void LockProdImpl() override;
+ virtual void UnlockProdImpl() override;
+
+ virtual void ProducerAcquireImpl() override {}
+ virtual void ProducerReleaseImpl() override {}
+ virtual void ProducerReadReleaseImpl() override;
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+
+ virtual void Commit() override;
+
+ virtual void WaitForBufferOwnership() override;
+
+ virtual bool IsBufferAvailable() const override;
+
+ bool IsValid() const override;
+};
+
+class SurfaceFactory_SurfaceTexture final : public SurfaceFactory {
+ public:
+ explicit SurfaceFactory_SurfaceTexture(GLContext&);
+
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_SurfaceTexture::Create(desc);
+ }
+};
+
+#endif // MOZ_WIDGET_ANDROID
+
+} // namespace gl
+
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_EGL_H_ */
diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp
new file mode 100644
index 0000000000..5b33088e2e
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGL.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceGL.h"
+
+#include "GLBlitHelper.h"
+#include "GLContext.h"
+#include "GLReadTexImageHelper.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/layers/TextureForwarder.h"
+#include "ScopedGLHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+/*static*/
+UniquePtr<SharedSurface_Basic> SharedSurface_Basic::Create(
+ const SharedSurfaceDesc& desc) {
+ auto fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false);
+ if (!fb) return nullptr;
+
+ return AsUnique(new SharedSurface_Basic(desc, std::move(fb)));
+}
+
+SharedSurface_Basic::SharedSurface_Basic(const SharedSurfaceDesc& desc,
+ UniquePtr<MozFramebuffer>&& fb)
+ : SharedSurface(desc, std::move(fb)) {}
+
+Maybe<layers::SurfaceDescriptor> SharedSurface_Basic::ToSurfaceDescriptor() {
+ return Nothing();
+}
+
+////////////////////////////////////////////////////////////////////////
+
+SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext& gl)
+ : SurfaceFactory({&gl, SharedSurfaceType::Basic,
+ layers::TextureType::Unknown, true}) {}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h
new file mode 100644
index 0000000000..fef3d59fb0
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGL.h
@@ -0,0 +1,42 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACE_GL_H_
+#define SHARED_SURFACE_GL_H_
+
+#include "SharedSurface.h"
+
+namespace mozilla {
+namespace gl {
+
+class MozFramebuffer;
+
+// For readback and bootstrapping:
+class SharedSurface_Basic final : public SharedSurface {
+ public:
+ static UniquePtr<SharedSurface_Basic> Create(const SharedSurfaceDesc&);
+
+ private:
+ SharedSurface_Basic(const SharedSurfaceDesc& desc,
+ UniquePtr<MozFramebuffer>&& fb);
+
+ public:
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+};
+
+class SurfaceFactory_Basic final : public SurfaceFactory {
+ public:
+ explicit SurfaceFactory_Basic(GLContext& gl);
+
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ return SharedSurface_Basic::Create(desc);
+ }
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // SHARED_SURFACE_GL_H_
diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp
new file mode 100644
index 0000000000..1fd0f22d31
--- /dev/null
+++ b/gfx/gl/SharedSurfaceIO.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SharedSurfaceIO.h"
+
+#include "GLContextCGL.h"
+#include "MozFramebuffer.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/gfx/MacIOSurface.h"
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
+#include "mozilla/layers/LayersTypes.h"
+#include "ScopedGLHelpers.h"
+
+namespace mozilla {
+namespace gl {
+
+// -
+// Factory
+
+SurfaceFactory_IOSurface::SurfaceFactory_IOSurface(GLContext& gl)
+ : SurfaceFactory({&gl, SharedSurfaceType::IOSurface,
+ layers::TextureType::MacIOSurface, true}),
+ mMaxDims(gfx::IntSize::Truncate(MacIOSurface::GetMaxWidth(),
+ MacIOSurface::GetMaxHeight())) {}
+
+// -
+// Surface
+
+static void BackTextureWithIOSurf(GLContext* const gl, const GLuint tex,
+ MacIOSurface* const ioSurf) {
+ MOZ_ASSERT(gl->IsCurrent());
+
+ ScopedBindTexture texture(gl, tex, LOCAL_GL_TEXTURE_RECTANGLE_ARB);
+
+ gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+ LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
+ gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB,
+ LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
+ gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S,
+ LOCAL_GL_CLAMP_TO_EDGE);
+ gl->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T,
+ LOCAL_GL_CLAMP_TO_EDGE);
+
+ CGLContextObj cgl = GLContextCGL::Cast(gl)->GetCGLContext();
+ MOZ_ASSERT(cgl);
+
+ ioSurf->CGLTexImageIOSurface2D(gl, cgl, 0);
+}
+
+/*static*/
+UniquePtr<SharedSurface_IOSurface> SharedSurface_IOSurface::Create(
+ const SharedSurfaceDesc& desc) {
+ const auto& size = desc.size;
+ const RefPtr<MacIOSurface> ioSurf =
+ MacIOSurface::CreateIOSurface(size.width, size.height, true);
+ if (!ioSurf) {
+ NS_WARNING("Failed to create MacIOSurface.");
+ return nullptr;
+ }
+
+ ioSurf->SetColorSpace(desc.colorSpace);
+
+ // -
+
+ auto tex = MakeUnique<Texture>(*desc.gl);
+ BackTextureWithIOSurf(desc.gl, tex->name, ioSurf);
+
+ const GLenum target = LOCAL_GL_TEXTURE_RECTANGLE;
+ auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false,
+ target, tex->name);
+ if (!fb) return nullptr;
+
+ return AsUnique(
+ new SharedSurface_IOSurface(desc, std::move(fb), std::move(tex), ioSurf));
+}
+
+SharedSurface_IOSurface::SharedSurface_IOSurface(
+ const SharedSurfaceDesc& desc, UniquePtr<MozFramebuffer> fb,
+ UniquePtr<Texture> tex, const RefPtr<MacIOSurface>& ioSurf)
+ : SharedSurface(desc, std::move(fb)),
+ mTex(std::move(tex)),
+ mIOSurf(ioSurf) {}
+
+SharedSurface_IOSurface::~SharedSurface_IOSurface() = default;
+
+void SharedSurface_IOSurface::ProducerReleaseImpl() {
+ const auto& gl = mDesc.gl;
+ if (!gl) return;
+ gl->MakeCurrent();
+ gl->fFlush();
+}
+
+Maybe<layers::SurfaceDescriptor>
+SharedSurface_IOSurface::ToSurfaceDescriptor() {
+ const bool isOpaque = false; // RGBA
+ return Some(layers::SurfaceDescriptorMacIOSurface(
+ mIOSurf->GetIOSurfaceID(), isOpaque, mIOSurf->GetYUVColorSpace()));
+}
+
+} // namespace gl
+} // namespace mozilla
diff --git a/gfx/gl/SharedSurfaceIO.h b/gfx/gl/SharedSurfaceIO.h
new file mode 100644
index 0000000000..938173b982
--- /dev/null
+++ b/gfx/gl/SharedSurfaceIO.h
@@ -0,0 +1,64 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SHARED_SURFACEIO_H_
+#define SHARED_SURFACEIO_H_
+
+#include "mozilla/RefPtr.h"
+#include "SharedSurface.h"
+
+class MacIOSurface;
+
+namespace mozilla {
+namespace gl {
+
+class Texture;
+
+class SharedSurface_IOSurface final : public SharedSurface {
+ public:
+ const UniquePtr<Texture> mTex;
+ const RefPtr<MacIOSurface> mIOSurf;
+
+ static UniquePtr<SharedSurface_IOSurface> Create(const SharedSurfaceDesc&);
+
+ private:
+ SharedSurface_IOSurface(const SharedSurfaceDesc&, UniquePtr<MozFramebuffer>,
+ UniquePtr<Texture>, const RefPtr<MacIOSurface>&);
+
+ public:
+ ~SharedSurface_IOSurface();
+
+ virtual void LockProdImpl() override {}
+ virtual void UnlockProdImpl() override {}
+
+ virtual void ProducerAcquireImpl() override {}
+ virtual void ProducerReleaseImpl() override;
+
+ virtual bool NeedsIndirectReads() const override { return true; }
+
+ Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
+};
+
+class SurfaceFactory_IOSurface : public SurfaceFactory {
+ public:
+ const gfx::IntSize mMaxDims;
+
+ explicit SurfaceFactory_IOSurface(GLContext& gl);
+
+ virtual UniquePtr<SharedSurface> CreateSharedImpl(
+ const SharedSurfaceDesc& desc) override {
+ if (desc.size.width > mMaxDims.width ||
+ desc.size.height > mMaxDims.height) {
+ return nullptr;
+ }
+ return SharedSurface_IOSurface::Create(desc);
+ }
+};
+
+} // namespace gl
+
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACEIO_H_ */
diff --git a/gfx/gl/SurfaceTypes.h b/gfx/gl/SurfaceTypes.h
new file mode 100644
index 0000000000..5967b6f7b4
--- /dev/null
+++ b/gfx/gl/SurfaceTypes.h
@@ -0,0 +1,35 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef SURFACE_TYPES_H_
+#define SURFACE_TYPES_H_
+
+#include <cstdint>
+
+namespace mozilla {
+namespace layers {
+class LayersIPCChannel;
+} // namespace layers
+
+namespace gl {
+
+enum class SharedSurfaceType : uint8_t {
+ Basic,
+ EGLImageShare,
+ EGLSurfaceANGLE,
+ DXGLInterop,
+ DXGLInterop2,
+ IOSurface,
+ GLXDrawable,
+ SharedGLTexture,
+ AndroidSurfaceTexture,
+ AndroidHardwareBuffer,
+ EGLSurfaceDMABUF,
+};
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // SURFACE_TYPES_H_
diff --git a/gfx/gl/WGLLibrary.h b/gfx/gl/WGLLibrary.h
new file mode 100644
index 0000000000..82c764b3db
--- /dev/null
+++ b/gfx/gl/WGLLibrary.h
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GLContextTypes.h"
+#include "GLLibraryLoader.h"
+#include "mozilla/UniquePtr.h"
+#include <windows.h>
+
+struct PRLibrary;
+
+namespace mozilla {
+namespace gl {
+/*
+struct ScopedDC
+{
+ const HDC mDC;
+
+ ScopedDC() = delete;
+ virtual ~ScopedDC() = 0;
+};
+
+struct WindowDC final : public ScopedDC
+{
+ const HWND mWindow;
+
+ WindowDC() = delete;
+ ~WindowDC();
+};
+
+struct PBufferDC final : public ScopedDC
+{
+ const HWND mWindow;
+
+ PBufferDC() = delete;
+ ~PBufferDC();
+};
+*/
+class WGLLibrary {
+ public:
+ ~WGLLibrary() { Reset(); }
+
+ private:
+ void Reset();
+
+ public:
+ struct {
+ HGLRC(GLAPIENTRY* fCreateContext)(HDC);
+ BOOL(GLAPIENTRY* fDeleteContext)(HGLRC);
+ BOOL(GLAPIENTRY* fMakeCurrent)(HDC, HGLRC);
+ PROC(GLAPIENTRY* fGetProcAddress)(LPCSTR);
+ HGLRC(GLAPIENTRY* fGetCurrentContext)(void);
+ HDC(GLAPIENTRY* fGetCurrentDC)(void);
+ // BOOL (GLAPIENTRY * fShareLists) (HGLRC oldContext, HGLRC newContext);
+ HANDLE(GLAPIENTRY* fCreatePbuffer)
+ (HDC hDC, int iPixelFormat, int iWidth, int iHeight,
+ const int* piAttribList);
+ BOOL(GLAPIENTRY* fDestroyPbuffer)(HANDLE hPbuffer);
+ HDC(GLAPIENTRY* fGetPbufferDC)(HANDLE hPbuffer);
+ int(GLAPIENTRY* fReleasePbufferDC)(HANDLE hPbuffer, HDC dc);
+ // BOOL (GLAPIENTRY * fBindTexImage) (HANDLE hPbuffer, int iBuffer);
+ // BOOL (GLAPIENTRY * fReleaseTexImage) (HANDLE hPbuffer, int iBuffer);
+ BOOL(GLAPIENTRY* fChoosePixelFormat)
+ (HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList,
+ UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
+ // BOOL (GLAPIENTRY * fGetPixelFormatAttribiv) (HDC hdc,
+ // int iPixelFormat,
+ // int iLayerPlane,
+ // UINT nAttributes,
+ // int* piAttributes,
+ // int* piValues);
+ const char*(GLAPIENTRY* fGetExtensionsStringARB)(HDC hdc);
+ HGLRC(GLAPIENTRY* fCreateContextAttribsARB)
+ (HDC hdc, HGLRC hShareContext, const int* attribList);
+ // WGL_NV_DX_interop:
+ BOOL(GLAPIENTRY* fDXSetResourceShareHandleNV)
+ (void* dxObject, HANDLE shareHandle);
+ HANDLE(GLAPIENTRY* fDXOpenDeviceNV)(void* dxDevice);
+ BOOL(GLAPIENTRY* fDXCloseDeviceNV)(HANDLE hDevice);
+ HANDLE(GLAPIENTRY* fDXRegisterObjectNV)
+ (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access);
+ BOOL(GLAPIENTRY* fDXUnregisterObjectNV)(HANDLE hDevice, HANDLE hObject);
+ BOOL(GLAPIENTRY* fDXObjectAccessNV)(HANDLE hObject, GLenum access);
+ BOOL(GLAPIENTRY* fDXLockObjectsNV)
+ (HANDLE hDevice, GLint count, HANDLE* hObjects);
+ BOOL(GLAPIENTRY* fDXUnlockObjectsNV)
+ (HANDLE hDevice, GLint count, HANDLE* hObjects);
+ } mSymbols = {};
+
+ bool EnsureInitialized();
+ // UniquePtr<WindowDC> CreateDummyWindow();
+ HGLRC CreateContextWithFallback(HDC dc, bool tryRobustBuffers) const;
+
+ bool HasDXInterop2() const { return bool(mSymbols.fDXOpenDeviceNV); }
+ bool IsInitialized() const { return mInitialized; }
+ auto GetOGLLibrary() const { return mOGLLibrary; }
+ auto RootDc() const { return mRootDc; }
+ SymbolLoader GetSymbolLoader() const;
+
+ private:
+ bool mInitialized = false;
+ PRLibrary* mOGLLibrary;
+ bool mHasRobustness;
+ HWND mDummyWindow;
+ HDC mRootDc;
+ HGLRC mDummyGlrc;
+};
+
+// a global WGLLibrary instance
+extern WGLLibrary sWGLLib;
+
+} /* namespace gl */
+} /* namespace mozilla */
diff --git a/gfx/gl/gtest/TestColorspaces.cpp b/gfx/gl/gtest/TestColorspaces.cpp
new file mode 100644
index 0000000000..c437e204af
--- /dev/null
+++ b/gfx/gl/gtest/TestColorspaces.cpp
@@ -0,0 +1,698 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "gtest/gtest.h"
+#include "Colorspaces.h"
+
+#include <array>
+#include <limits>
+
+namespace mozilla::color {
+mat4 YuvFromYcbcr(const YcbcrDesc&);
+float TfFromLinear(const PiecewiseGammaDesc&, float linear);
+float LinearFromTf(const PiecewiseGammaDesc&, float tf);
+mat3 XyzFromLinearRgb(const Chromaticities&);
+} // namespace mozilla::color
+
+using namespace mozilla::color;
+
+auto Calc8From8(const ColorspaceTransform& ct, const ivec3 in8) {
+ const auto in = vec3(in8) / vec3(255);
+ const auto out = ct.DstFromSrc(in);
+ const auto out8 = ivec3(round(out * vec3(255)));
+ return out8;
+}
+
+auto Sample8From8(const Lut3& lut, const vec3 in8) {
+ const auto in = in8 / vec3(255);
+ const auto out = lut.Sample(in);
+ const auto out8 = ivec3(round(out * vec3(255)));
+ return out8;
+}
+
+TEST(Colorspaces, YcbcrDesc_Narrow8)
+{
+ const auto m = YuvFromYcbcr(YcbcrDesc::Narrow8());
+
+ const auto Yuv8 = [&](const ivec3 ycbcr8) {
+ const auto ycbcr = vec4(vec3(ycbcr8) / 255, 1);
+ const auto yuv = m * ycbcr;
+ return ivec3(round(yuv * 255));
+ };
+
+ EXPECT_EQ(Yuv8({{16, 128, 128}}), (ivec3{{0, 0, 0}}));
+ EXPECT_EQ(Yuv8({{17, 128, 128}}), (ivec3{{1, 0, 0}}));
+ // y = 0.5 => (16 + 235) / 2 = 125.5
+ EXPECT_EQ(Yuv8({{125, 128, 128}}), (ivec3{{127, 0, 0}}));
+ EXPECT_EQ(Yuv8({{126, 128, 128}}), (ivec3{{128, 0, 0}}));
+ EXPECT_EQ(Yuv8({{234, 128, 128}}), (ivec3{{254, 0, 0}}));
+ EXPECT_EQ(Yuv8({{235, 128, 128}}), (ivec3{{255, 0, 0}}));
+
+ // Check that we get the naive out-of-bounds behavior we'd expect:
+ EXPECT_EQ(Yuv8({{15, 128, 128}}), (ivec3{{-1, 0, 0}}));
+ EXPECT_EQ(Yuv8({{236, 128, 128}}), (ivec3{{256, 0, 0}}));
+}
+
+TEST(Colorspaces, YcbcrDesc_Full8)
+{
+ const auto m = YuvFromYcbcr(YcbcrDesc::Full8());
+
+ const auto Yuv8 = [&](const ivec3 ycbcr8) {
+ const auto ycbcr = vec4(vec3(ycbcr8) / 255, 1);
+ const auto yuv = m * ycbcr;
+ return ivec3(round(yuv * 255));
+ };
+
+ EXPECT_EQ(Yuv8({{0, 128, 128}}), (ivec3{{0, 0, 0}}));
+ EXPECT_EQ(Yuv8({{1, 128, 128}}), (ivec3{{1, 0, 0}}));
+ EXPECT_EQ(Yuv8({{127, 128, 128}}), (ivec3{{127, 0, 0}}));
+ EXPECT_EQ(Yuv8({{128, 128, 128}}), (ivec3{{128, 0, 0}}));
+ EXPECT_EQ(Yuv8({{254, 128, 128}}), (ivec3{{254, 0, 0}}));
+ EXPECT_EQ(Yuv8({{255, 128, 128}}), (ivec3{{255, 0, 0}}));
+}
+
+TEST(Colorspaces, YcbcrDesc_Float)
+{
+ const auto m = YuvFromYcbcr(YcbcrDesc::Float());
+
+ const auto Yuv8 = [&](const vec3 ycbcr8) {
+ const auto ycbcr = vec4(vec3(ycbcr8) / 255, 1);
+ const auto yuv = m * ycbcr;
+ return ivec3(round(yuv * 255));
+ };
+
+ EXPECT_EQ(Yuv8({{0, 0.5 * 255, 0.5 * 255}}), (ivec3{{0, 0, 0}}));
+ EXPECT_EQ(Yuv8({{1, 0.5 * 255, 0.5 * 255}}), (ivec3{{1, 0, 0}}));
+ EXPECT_EQ(Yuv8({{127, 0.5 * 255, 0.5 * 255}}), (ivec3{{127, 0, 0}}));
+ EXPECT_EQ(Yuv8({{128, 0.5 * 255, 0.5 * 255}}), (ivec3{{128, 0, 0}}));
+ EXPECT_EQ(Yuv8({{254, 0.5 * 255, 0.5 * 255}}), (ivec3{{254, 0, 0}}));
+ EXPECT_EQ(Yuv8({{255, 0.5 * 255, 0.5 * 255}}), (ivec3{{255, 0, 0}}));
+}
+
+TEST(Colorspaces, ColorspaceTransform_Rec709Narrow)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Narrow8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {},
+ };
+ const auto ct = ColorspaceTransform::Create(src, dst);
+
+ EXPECT_EQ(Calc8From8(ct, {{16, 128, 128}}), (ivec3{0}));
+ EXPECT_EQ(Calc8From8(ct, {{17, 128, 128}}), (ivec3{1}));
+ EXPECT_EQ(Calc8From8(ct, {{126, 128, 128}}), (ivec3{128}));
+ EXPECT_EQ(Calc8From8(ct, {{234, 128, 128}}), (ivec3{254}));
+ EXPECT_EQ(Calc8From8(ct, {{235, 128, 128}}), (ivec3{255}));
+
+ // Check that we get the naive out-of-bounds behavior we'd expect:
+ EXPECT_EQ(Calc8From8(ct, {{15, 128, 128}}), (ivec3{-1}));
+ EXPECT_EQ(Calc8From8(ct, {{236, 128, 128}}), (ivec3{256}));
+}
+
+TEST(Colorspaces, LutSample_Rec709Float)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Float()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {},
+ };
+ const auto lut = ColorspaceTransform::Create(src, dst).ToLut3();
+
+ EXPECT_EQ(Sample8From8(lut, {{0, 0.5 * 255, 0.5 * 255}}), (ivec3{0}));
+ EXPECT_EQ(Sample8From8(lut, {{1, 0.5 * 255, 0.5 * 255}}), (ivec3{1}));
+ EXPECT_EQ(Sample8From8(lut, {{127, 0.5 * 255, 0.5 * 255}}), (ivec3{127}));
+ EXPECT_EQ(Sample8From8(lut, {{128, 0.5 * 255, 0.5 * 255}}), (ivec3{128}));
+ EXPECT_EQ(Sample8From8(lut, {{254, 0.5 * 255, 0.5 * 255}}), (ivec3{254}));
+ EXPECT_EQ(Sample8From8(lut, {{255, 0.5 * 255, 0.5 * 255}}), (ivec3{255}));
+}
+
+TEST(Colorspaces, LutSample_Rec709Narrow)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Narrow8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {},
+ };
+ const auto lut = ColorspaceTransform::Create(src, dst).ToLut3();
+
+ EXPECT_EQ(Sample8From8(lut, {{16, 128, 128}}), (ivec3{0}));
+ EXPECT_EQ(Sample8From8(lut, {{17, 128, 128}}), (ivec3{1}));
+ EXPECT_EQ(Sample8From8(lut, {{int((235 + 16) / 2), 128, 128}}), (ivec3{127}));
+ EXPECT_EQ(Sample8From8(lut, {{int((235 + 16) / 2) + 1, 128, 128}}),
+ (ivec3{128}));
+ EXPECT_EQ(Sample8From8(lut, {{234, 128, 128}}), (ivec3{254}));
+ EXPECT_EQ(Sample8From8(lut, {{235, 128, 128}}), (ivec3{255}));
+}
+
+TEST(Colorspaces, LutSample_Rec709Full)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Full8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {},
+ };
+ const auto lut = ColorspaceTransform::Create(src, dst).ToLut3();
+
+ EXPECT_EQ(Sample8From8(lut, {{0, 128, 128}}), (ivec3{0}));
+ EXPECT_EQ(Sample8From8(lut, {{1, 128, 128}}), (ivec3{1}));
+ EXPECT_EQ(Sample8From8(lut, {{16, 128, 128}}), (ivec3{16}));
+ EXPECT_EQ(Sample8From8(lut, {{128, 128, 128}}), (ivec3{128}));
+ EXPECT_EQ(Sample8From8(lut, {{235, 128, 128}}), (ivec3{235}));
+ EXPECT_EQ(Sample8From8(lut, {{254, 128, 128}}), (ivec3{254}));
+ EXPECT_EQ(Sample8From8(lut, {{255, 128, 128}}), (ivec3{255}));
+}
+
+TEST(Colorspaces, PiecewiseGammaDesc_Srgb)
+{
+ const auto tf = PiecewiseGammaDesc::Srgb();
+
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x00 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x01 / 255.0) * 255)), 0x0d);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x37 / 255.0) * 255)), 0x80);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x80 / 255.0) * 255)), 0xbc);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xfd / 255.0) * 255)), 0xfe);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xfe / 255.0) * 255)), 0xff);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xff / 255.0) * 255)), 0xff);
+
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x00 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x01 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x06 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x07 / 255.0) * 255)), 0x01);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x0d / 255.0) * 255)), 0x01);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x80 / 255.0) * 255)), 0x37);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xbc / 255.0) * 255)), 0x80);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xfe / 255.0) * 255)), 0xfd);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xff / 255.0) * 255)), 0xff);
+}
+
+TEST(Colorspaces, PiecewiseGammaDesc_Rec709)
+{
+ const auto tf = PiecewiseGammaDesc::Rec709();
+
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x00 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x01 / 255.0) * 255)), 0x05);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x43 / 255.0) * 255)), 0x80);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0x80 / 255.0) * 255)), 0xb4);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xfd / 255.0) * 255)), 0xfe);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xfe / 255.0) * 255)), 0xff);
+ EXPECT_EQ(int(roundf(TfFromLinear(tf, 0xff / 255.0) * 255)), 0xff);
+
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x00 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x01 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x02 / 255.0) * 255)), 0x00);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x03 / 255.0) * 255)), 0x01);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x05 / 255.0) * 255)), 0x01);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0x80 / 255.0) * 255)), 0x43);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xb4 / 255.0) * 255)), 0x80);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xfe / 255.0) * 255)), 0xfd);
+ EXPECT_EQ(int(roundf(LinearFromTf(tf, 0xff / 255.0) * 255)), 0xff);
+}
+
+TEST(Colorspaces, ColorspaceTransform_PiecewiseGammaDesc)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ {},
+ {},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ PiecewiseGammaDesc::Srgb(),
+ {},
+ };
+ const auto toGamma = ColorspaceTransform::Create(src, dst);
+ const auto toLinear = ColorspaceTransform::Create(dst, src);
+
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0x00}), (ivec3{0x00}));
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0x01}), (ivec3{0x0d}));
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0x37}), (ivec3{0x80}));
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0x80}), (ivec3{0xbc}));
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0xfd}), (ivec3{0xfe}));
+ EXPECT_EQ(Calc8From8(toGamma, ivec3{0xff}), (ivec3{0xff}));
+
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0x00}), (ivec3{0x00}));
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0x0d}), (ivec3{0x01}));
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0x80}), (ivec3{0x37}));
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0xbc}), (ivec3{0x80}));
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0xfe}), (ivec3{0xfd}));
+ EXPECT_EQ(Calc8From8(toLinear, ivec3{0xff}), (ivec3{0xff}));
+}
+
+// -
+// Actual end-to-end tests
+
+TEST(Colorspaces, SrgbFromRec709)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Narrow8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ PiecewiseGammaDesc::Srgb(),
+ {},
+ };
+ const auto ct = ColorspaceTransform::Create(src, dst);
+
+ EXPECT_EQ(Calc8From8(ct, ivec3{{16, 128, 128}}), (ivec3{0}));
+ EXPECT_EQ(Calc8From8(ct, ivec3{{17, 128, 128}}), (ivec3{3}));
+ EXPECT_EQ(Calc8From8(ct, ivec3{{115, 128, 128}}), (ivec3{128}));
+ EXPECT_EQ(Calc8From8(ct, ivec3{{126, 128, 128}}), (ivec3{140}));
+ EXPECT_EQ(Calc8From8(ct, ivec3{{234, 128, 128}}), (ivec3{254}));
+ EXPECT_EQ(Calc8From8(ct, ivec3{{235, 128, 128}}), (ivec3{255}));
+}
+
+TEST(Colorspaces, SrgbFromDisplayP3)
+{
+ const auto p3C = ColorspaceDesc{
+ Chromaticities::DisplayP3(),
+ PiecewiseGammaDesc::DisplayP3(),
+ };
+ const auto srgbC = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ PiecewiseGammaDesc::Srgb(),
+ };
+ const auto srgbLinearC = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ {},
+ };
+ const auto srgbFromP3 = ColorspaceTransform::Create(p3C, srgbC);
+ const auto srgbLinearFromP3 = ColorspaceTransform::Create(p3C, srgbLinearC);
+
+ // E.g.
+ // https://colorjs.io/apps/convert/?color=color(display-p3%200.4%200.8%200.4)&precision=4
+ auto srgb = srgbFromP3.DstFromSrc(vec3{{0.4, 0.8, 0.4}});
+ EXPECT_NEAR(srgb.x(), 0.179, 0.001);
+ EXPECT_NEAR(srgb.y(), 0.812, 0.001);
+ EXPECT_NEAR(srgb.z(), 0.342, 0.001);
+ auto srgbLinear = srgbLinearFromP3.DstFromSrc(vec3{{0.4, 0.8, 0.4}});
+ EXPECT_NEAR(srgbLinear.x(), 0.027, 0.001);
+ EXPECT_NEAR(srgbLinear.y(), 0.624, 0.001);
+ EXPECT_NEAR(srgbLinear.z(), 0.096, 0.001);
+}
+
+// -
+
+template <class Fn, class Tuple, size_t... I>
+constexpr auto map_tups_seq(const Tuple& a, const Tuple& b, const Fn& fn,
+ std::index_sequence<I...>) {
+ return std::tuple{fn(std::get<I>(a), std::get<I>(b))...};
+}
+template <class Fn, class Tuple>
+constexpr auto map_tups(const Tuple& a, const Tuple& b, const Fn& fn) {
+ return map_tups_seq(a, b, fn,
+ std::make_index_sequence<std::tuple_size_v<Tuple>>{});
+}
+
+template <class Fn, class Tuple>
+constexpr auto cmp_tups_all(const Tuple& a, const Tuple& b, const Fn& fn) {
+ bool all = true;
+ map_tups(a, b, [&](const auto& a, const auto& b) { return all &= fn(a, b); });
+ return all;
+}
+
+struct Stats {
+ double mean = 0;
+ double variance = 0;
+ double min = std::numeric_limits<double>::infinity();
+ double max = -std::numeric_limits<double>::infinity();
+
+ template <class T>
+ static Stats For(const T& iterable) {
+ auto ret = Stats{};
+ for (const auto& cur : iterable) {
+ ret.mean += cur;
+ ret.min = std::min(ret.min, cur);
+ ret.max = std::max(ret.max, cur);
+ }
+ ret.mean /= iterable.size();
+ // Gather mean first before we can calc variance.
+ for (const auto& cur : iterable) {
+ ret.variance += pow(cur - ret.mean, 2);
+ }
+ ret.variance /= iterable.size();
+ return ret;
+ }
+
+ template <class T, class U>
+ static Stats Diff(const T& a, const U& b) {
+ MOZ_ASSERT(a.size() == b.size());
+ std::vector<double> diff;
+ diff.reserve(a.size());
+ for (size_t i = 0; i < diff.capacity(); i++) {
+ diff.push_back(a[i] - b[i]);
+ }
+ return Stats::For(diff);
+ }
+
+ double standardDeviation() const { return sqrt(variance); }
+
+ friend std::ostream& operator<<(std::ostream& s, const Stats& a) {
+ return s << "Stats"
+ << "{ mean:" << a.mean << ", stddev:" << a.standardDeviation()
+ << ", min:" << a.min << ", max:" << a.max << " }";
+ }
+
+ struct Error {
+ double absmean = std::numeric_limits<double>::infinity();
+ double stddev = std::numeric_limits<double>::infinity();
+ double absmax = std::numeric_limits<double>::infinity();
+
+ constexpr auto Fields() const { return std::tie(absmean, stddev, absmax); }
+
+ template <class Fn>
+ friend constexpr bool cmp_all(const Error& a, const Error& b,
+ const Fn& fn) {
+ return cmp_tups_all(a.Fields(), b.Fields(), fn);
+ }
+ friend constexpr bool operator<(const Error& a, const Error& b) {
+ return cmp_all(a, b, [](const auto& a, const auto& b) { return a < b; });
+ }
+ friend constexpr bool operator<=(const Error& a, const Error& b) {
+ return cmp_all(a, b, [](const auto& a, const auto& b) { return a <= b; });
+ }
+
+ friend std::ostream& operator<<(std::ostream& s, const Error& a) {
+ return s << "Stats::Error"
+ << "{ absmean:" << a.absmean << ", stddev:" << a.stddev
+ << ", absmax:" << a.absmax << " }";
+ }
+ };
+
+ operator Error() const {
+ return {abs(mean), standardDeviation(), std::max(abs(min), abs(max))};
+ }
+};
+static_assert(Stats::Error{0, 0, 0} < Stats::Error{1, 1, 1});
+static_assert(!(Stats::Error{0, 1, 0} < Stats::Error{1, 1, 1}));
+static_assert(Stats::Error{0, 1, 0} <= Stats::Error{1, 1, 1});
+static_assert(!(Stats::Error{0, 2, 0} <= Stats::Error{1, 1, 1}));
+
+// -
+
+static Stats StatsForLutError(const ColorspaceTransform& ct,
+ const ivec3 srcQuants, const ivec3 dstQuants) {
+ const auto lut = ct.ToLut3();
+
+ const auto dstScale = vec3(dstQuants - 1);
+
+ std::vector<double> quantErrors;
+ quantErrors.reserve(srcQuants.x() * srcQuants.y() * srcQuants.z());
+ ForEachSampleWithin(srcQuants, [&](const vec3& src) {
+ const auto sampled = lut.Sample(src);
+ const auto actual = ct.DstFromSrc(src);
+ const auto isampled = ivec3(round(sampled * dstScale));
+ const auto iactual = ivec3(round(actual * dstScale));
+ const auto ierr = abs(isampled - iactual);
+ const auto quantError = dot(ierr, ivec3{1});
+ quantErrors.push_back(quantError);
+ if (quantErrors.size() % 100000 == 0) {
+ printf("%zu of %zu\n", quantErrors.size(), quantErrors.capacity());
+ }
+ });
+
+ const auto quantErrStats = Stats::For(quantErrors);
+ return quantErrStats;
+}
+
+TEST(Colorspaces, LutError_Rec709Full_Rec709Rgb)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Full8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {},
+ };
+ const auto ct = ColorspaceTransform::Create(src, dst);
+ const auto stats = StatsForLutError(ct, ivec3{64}, ivec3{256});
+ EXPECT_NEAR(stats.mean, 0.000, 0.001);
+ EXPECT_NEAR(stats.standardDeviation(), 0.008, 0.001);
+ EXPECT_NEAR(stats.min, 0, 0.001);
+ EXPECT_NEAR(stats.max, 1, 0.001);
+}
+
+TEST(Colorspaces, LutError_Rec709Full_Srgb)
+{
+ const auto src = ColorspaceDesc{
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ {{YuvLumaCoeffs::Rec709(), YcbcrDesc::Full8()}},
+ };
+ const auto dst = ColorspaceDesc{
+ Chromaticities::Srgb(),
+ PiecewiseGammaDesc::Srgb(),
+ {},
+ };
+ const auto ct = ColorspaceTransform::Create(src, dst);
+ const auto stats = StatsForLutError(ct, ivec3{64}, ivec3{256});
+ EXPECT_NEAR(stats.mean, 0.530, 0.001);
+ EXPECT_NEAR(stats.standardDeviation(), 1.674, 0.001);
+ EXPECT_NEAR(stats.min, 0, 0.001);
+ EXPECT_NEAR(stats.max, 17, 0.001);
+}
+
+// -
+// https://www.reedbeta.com/blog/python-like-enumerate-in-cpp17/
+
+template <typename T, typename TIter = decltype(std::begin(std::declval<T>())),
+ typename = decltype(std::end(std::declval<T>()))>
+constexpr auto enumerate(T&& iterable) {
+ struct iterator {
+ size_t i;
+ TIter iter;
+ bool operator!=(const iterator& other) const { return iter != other.iter; }
+ void operator++() {
+ ++i;
+ ++iter;
+ }
+ auto operator*() const { return std::tie(i, *iter); }
+ };
+ struct iterable_wrapper {
+ T iterable;
+ auto begin() { return iterator{0, std::begin(iterable)}; }
+ auto end() { return iterator{0, std::end(iterable)}; }
+ };
+ return iterable_wrapper{std::forward<T>(iterable)};
+}
+
+inline auto MakeLinear(const float from, const float to, const int n) {
+ std::vector<float> ret;
+ ret.resize(n);
+ for (auto [i, val] : enumerate(ret)) {
+ const auto t = i / float(ret.size() - 1);
+ val = from + (to - from) * t;
+ }
+ return ret;
+};
+
+inline auto MakeGamma(const float exp, const int n) {
+ std::vector<float> ret;
+ ret.resize(n);
+ for (auto [i, val] : enumerate(ret)) {
+ const auto t = i / float(ret.size() - 1);
+ val = powf(t, exp);
+ }
+ return ret;
+};
+
+// -
+
+TEST(Colorspaces, GuessGamma)
+{
+ EXPECT_NEAR(GuessGamma(MakeGamma(1, 11)), 1.0, 0);
+ EXPECT_NEAR(GuessGamma(MakeGamma(2.2, 11)), 2.2, 4.8e-8);
+ EXPECT_NEAR(GuessGamma(MakeGamma(1 / 2.2, 11)), 1 / 2.2, 1.7e-7);
+}
+
+// -
+
+template <class T, class U>
+float StdDev(const T& test, const U& ref) {
+ float sum = 0;
+ for (size_t i = 0; i < test.size(); i++) {
+ const auto diff = test[i] - ref[i];
+ sum += diff * diff;
+ }
+ const auto variance = sum / test.size();
+ return sqrt(variance);
+}
+
+template <class T>
+inline void AutoLinearFill(T& vals) {
+ LinearFill(vals, {
+ {0, 0},
+ {vals.size() - 1.0f, 1},
+ });
+}
+
+template <class T, class... More>
+auto MakeArray(const T& a0, const More&... args) {
+ return std::array<T, 1 + sizeof...(More)>{a0, static_cast<float>(args)...};
+}
+
+TEST(Colorspaces, LinearFill)
+{
+ EXPECT_NEAR(StdDev(MakeLinear(0, 1, 3), MakeArray<float>(0, 0.5, 1)), 0,
+ 0.001);
+
+ auto vals = std::vector<float>(3);
+ LinearFill(vals, {
+ {0, 0},
+ {vals.size() - 1.0f, 1},
+ });
+ EXPECT_NEAR(StdDev(vals, MakeArray<float>(0, 0.5, 1)), 0, 0.001);
+
+ LinearFill(vals, {
+ {0, 1},
+ {vals.size() - 1.0f, 0},
+ });
+ EXPECT_NEAR(StdDev(vals, MakeArray<float>(1, 0.5, 0)), 0, 0.001);
+}
+
+TEST(Colorspaces, DequantizeMonotonic)
+{
+ auto orig = std::vector<float>{0, 0, 0, 1, 1, 2};
+ auto vals = orig;
+ EXPECT_TRUE(IsMonotonic(vals));
+ EXPECT_TRUE(!IsMonotonic(vals, std::less<float>{}));
+ DequantizeMonotonic(vals);
+ EXPECT_TRUE(IsMonotonic(vals, std::less<float>{}));
+ EXPECT_LT(StdDev(vals, orig),
+ StdDev(MakeLinear(orig.front(), orig.back(), vals.size()), orig));
+}
+
+TEST(Colorspaces, InvertLut)
+{
+ const auto linear = MakeLinear(0, 1, 256);
+ auto linearFromSrgb = linear;
+ for (auto& val : linearFromSrgb) {
+ val = powf(val, 2.2);
+ }
+ auto srgbFromLinearExpected = linear;
+ for (auto& val : srgbFromLinearExpected) {
+ val = powf(val, 1 / 2.2);
+ }
+
+ auto srgbFromLinearViaInvert = linearFromSrgb;
+ InvertLut(linearFromSrgb, &srgbFromLinearViaInvert);
+ // I just want to appreciate that InvertLut is a non-analytical approximation,
+ // and yet it's extraordinarily close to the analytical inverse.
+ EXPECT_LE(Stats::Diff(srgbFromLinearViaInvert, srgbFromLinearExpected),
+ (Stats::Error{3e-6, 3e-6, 3e-5}));
+
+ const auto srcSrgb = MakeLinear(0, 1, 256);
+ auto roundtripSrgb = srcSrgb;
+ for (auto& srgb : roundtripSrgb) {
+ const auto linear = SampleOutByIn(linearFromSrgb, srgb);
+ const auto srgb2 = SampleOutByIn(srgbFromLinearViaInvert, linear);
+ // printf("[%f] %f -> %f -> %f\n", srgb2-srgb, srgb, linear, srgb2);
+ srgb = srgb2;
+ }
+ EXPECT_LE(Stats::Diff(roundtripSrgb, srcSrgb),
+ (Stats::Error{0.0013, 0.0046, 0.023}));
+}
+
+TEST(Colorspaces, XyzFromLinearRgb)
+{
+ const auto xyzd65FromLinearRgb = XyzFromLinearRgb(Chromaticities::Srgb());
+
+ // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
+ const auto XYZD65_FROM_LINEAR_RGB = mat3({
+ vec3{{0.4124564, 0.3575761, 0.1804375}},
+ vec3{{0.2126729, 0.7151522, 0.0721750}},
+ vec3{{0.0193339, 0.1191920, 0.9503041}},
+ });
+ EXPECT_NEAR(sqrt(dotDifference(xyzd65FromLinearRgb, XYZD65_FROM_LINEAR_RGB)),
+ 0, 0.001);
+}
+
+TEST(Colorspaces, ColorProfileConversionDesc_SrgbFromRec709)
+{
+ const auto srgb = ColorProfileDesc::From({
+ Chromaticities::Srgb(),
+ PiecewiseGammaDesc::Srgb(),
+ });
+ const auto rec709 = ColorProfileDesc::From({
+ Chromaticities::Rec709(),
+ PiecewiseGammaDesc::Rec709(),
+ });
+
+ {
+ const auto conv = ColorProfileConversionDesc::From({
+ .src = srgb,
+ .dst = srgb,
+ });
+ auto src = vec3(16.0);
+ auto dst = conv.Apply(src / 255) * 255;
+
+ const auto tfa = PiecewiseGammaDesc::Srgb();
+ const auto tfb = PiecewiseGammaDesc::Srgb();
+ const auto expected =
+ TfFromLinear(tfb, LinearFromTf(tfa, src.x() / 255)) * 255;
+
+ printf("%f %f %f\n", src.x(), src.y(), src.z());
+ printf("%f %f %f\n", dst.x(), dst.y(), dst.z());
+ EXPECT_LT(Stats::Diff(dst.data, vec3(expected).data), (Stats::Error{0.42}));
+ }
+ {
+ const auto conv = ColorProfileConversionDesc::From({
+ .src = rec709,
+ .dst = rec709,
+ });
+ auto src = vec3(16.0);
+ auto dst = conv.Apply(src / 255) * 255;
+
+ const auto tfa = PiecewiseGammaDesc::Rec709();
+ const auto tfb = PiecewiseGammaDesc::Rec709();
+ const auto expected =
+ TfFromLinear(tfb, LinearFromTf(tfa, src.x() / 255)) * 255;
+
+ printf("%f %f %f\n", src.x(), src.y(), src.z());
+ printf("%f %f %f\n", dst.x(), dst.y(), dst.z());
+ EXPECT_LT(Stats::Diff(dst.data, vec3(expected).data), (Stats::Error{1e-6}));
+ }
+ {
+ const auto conv = ColorProfileConversionDesc::From({
+ .src = rec709,
+ .dst = srgb,
+ });
+ auto src = vec3(16.0);
+ auto dst = conv.Apply(src / 255) * 255;
+
+ const auto tfa = PiecewiseGammaDesc::Rec709();
+ const auto tfb = PiecewiseGammaDesc::Srgb();
+ const auto expected =
+ TfFromLinear(tfb, LinearFromTf(tfa, src.x() / 255)) * 255;
+ printf("expected: %f\n", expected);
+ printf("%f %f %f\n", src.x(), src.y(), src.z());
+ printf("%f %f %f\n", dst.x(), dst.y(), dst.z());
+ EXPECT_LT(Stats::Diff(dst.data, vec3(expected).data), (Stats::Error{0.12}));
+ }
+}
diff --git a/gfx/gl/gtest/moz.build b/gfx/gl/gtest/moz.build
new file mode 100644
index 0000000000..5b57e3ded1
--- /dev/null
+++ b/gfx/gl/gtest/moz.build
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+LOCAL_INCLUDES += [
+ "/gfx/gl",
+]
+
+UNIFIED_SOURCES += [
+ "TestColorspaces.cpp",
+]
+
+FINAL_LIBRARY = "xul-gtest"
diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
new file mode 100644
index 0000000000..f45e85b8f4
--- /dev/null
+++ b/gfx/gl/moz.build
@@ -0,0 +1,163 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+gl_provider = "Null"
+
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
+ gl_provider = "WGL"
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+ gl_provider = "CGL"
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "uikit":
+ gl_provider = "EAGL"
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
+ gl_provider = "Linux"
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
+ gl_provider = "EGL"
+
+if CONFIG["MOZ_GL_PROVIDER"]:
+ gl_provider = CONFIG["MOZ_GL_PROVIDER"]
+
+EXPORTS += [
+ "AndroidSurfaceTexture.h",
+ "AutoMappable.h",
+ "Colorspaces.h",
+ "ForceDiscreteGPUHelperCGL.h",
+ "GfxTexturesReporter.h",
+ "GLBlitHelper.h",
+ "GLConsts.h",
+ "GLContext.h",
+ "GLContextEGL.h",
+ "GLContextProvider.h",
+ "GLContextProviderImpl.h",
+ "GLContextSymbols.h",
+ "GLContextTypes.h",
+ "GLDefs.h",
+ "GLLibraryEGL.h",
+ "GLLibraryLoader.h",
+ "GLReadTexImageHelper.h",
+ "GLScreenBuffer.h",
+ "GLTextureImage.h",
+ "GLTypes.h",
+ "GLUploadHelpers.h",
+ "HeapCopyOfStackArray.h",
+ "MozFramebuffer.h",
+ "ScopedGLHelpers.h",
+ "SharedSurface.h",
+ "SharedSurfaceEGL.h",
+ "SharedSurfaceGL.h",
+ "SurfaceTypes.h",
+]
+
+# Win32 is a special snowflake, for ANGLE
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
+ EXPORTS += [
+ "GLContextWGL.h",
+ "SharedSurfaceANGLE.h", # Needs <windows.h> for `HANDLE`.
+ "SharedSurfaceD3D11Interop.h",
+ "WGLLibrary.h",
+ ]
+ UNIFIED_SOURCES += [
+ "GLBlitHelperD3D.cpp",
+ "GLContextProviderWGL.cpp",
+ "SharedSurfaceANGLE.cpp",
+ "SharedSurfaceD3D11Interop.cpp",
+ ]
+
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
+ EXPORTS += [
+ "AndroidNativeWindow.h",
+ "SharedSurfaceAndroidHardwareBuffer.h",
+ ]
+ UNIFIED_SOURCES += [
+ "SharedSurfaceAndroidHardwareBuffer.cpp",
+ ]
+
+if gl_provider == "CGL":
+ # These files include Mac headers that are unfriendly to unified builds
+ SOURCES += [
+ "GLContextProviderCGL.mm",
+ ]
+ EXPORTS += [
+ "GLContextCGL.h",
+ "SharedSurfaceIO.h",
+ ]
+ # SharedSurfaceIO.cpp includes MacIOSurface.h which include Mac headers
+ # which define Size and Point types in root namespace with often conflict with
+ # our own types. While I haven't actually hit this issue in the present case,
+ # it's been an issue in gfx/layers so let's not risk it.
+ SOURCES += [
+ "SharedSurfaceIO.cpp",
+ ]
+ OS_LIBS += [
+ "-framework IOSurface",
+ ]
+
+elif gl_provider == "EAGL":
+ # These files include ObjC headers that are unfriendly to unified builds
+ SOURCES += [
+ "GLContextProviderEAGL.mm",
+ ]
+ EXPORTS += [
+ "GLContextEAGL.h",
+ ]
+
+elif gl_provider == "Linux":
+ # GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES
+ # as it includes X11 headers which cause conflicts.
+ SOURCES += [
+ "GLContextProviderLinux.cpp",
+ "SharedSurfaceDMABUF.cpp",
+ ]
+ EXPORTS += ["GLContextGLX.h", "GLXLibrary.h"]
+ if CONFIG["MOZ_X11"]:
+ SOURCES += ["GLContextProviderGLX.cpp"]
+
+UNIFIED_SOURCES += [
+ "AndroidSurfaceTexture.cpp",
+ "Colorspaces.cpp",
+ "GfxTexturesReporter.cpp",
+ "GLBlitHelper.cpp",
+ "GLContext.cpp",
+ "GLContextFeatures.cpp",
+ "GLContextProviderEGL.cpp",
+ "GLDebugUtils.cpp",
+ "GLLibraryEGL.cpp",
+ "GLLibraryLoader.cpp",
+ "GLReadTexImageHelper.cpp",
+ "GLTextureImage.cpp",
+ "GLUploadHelpers.cpp",
+ "MozFramebuffer.cpp",
+ "ScopedGLHelpers.cpp",
+ "SharedSurface.cpp",
+ "SharedSurfaceEGL.cpp",
+ "SharedSurfaceGL.cpp",
+]
+SOURCES += [
+ "GLScreenBuffer.cpp",
+]
+
+TEST_DIRS += [
+ "gtest",
+]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul"
+
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
+ CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
+ CFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
+
+CXXFLAGS += ["-Werror=switch"]
+
+if CONFIG["MOZ_WAYLAND"]:
+ CXXFLAGS += CONFIG["MOZ_WAYLAND_CFLAGS"]
+ CFLAGS += CONFIG["MOZ_WAYLAND_CFLAGS"]
+
+LOCAL_INCLUDES += CONFIG["SKIA_INCLUDES"]
+LOCAL_INCLUDES += [
+ "/gfx/cairo/cairo/src",
+]