diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /gfx/gl | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | uxp-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz |
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/gl')
76 files changed, 32648 insertions, 0 deletions
diff --git a/gfx/gl/AndroidSurfaceTexture.cpp b/gfx/gl/AndroidSurfaceTexture.cpp new file mode 100644 index 0000000000..3c8c81974a --- /dev/null +++ b/gfx/gl/AndroidSurfaceTexture.cpp @@ -0,0 +1,260 @@ +/* -*- 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/. */ + +#ifdef MOZ_WIDGET_ANDROID + +#include <map> +#include <android/native_window_jni.h> +#include <android/log.h> +#include "AndroidSurfaceTexture.h" +#include "gfxImageSurface.h" +#include "gfxPrefs.h" +#include "AndroidBridge.h" +#include "nsThreadUtils.h" +#include "mozilla/gfx/Matrix.h" +#include "GeneratedJNINatives.h" +#include "GLContext.h" + +using namespace mozilla; + +namespace mozilla { +namespace gl { + +class AndroidSurfaceTexture::Listener + : public java::SurfaceTextureListener::Natives<Listener> +{ + using Base = java::SurfaceTextureListener::Natives<Listener>; + + const nsCOMPtr<nsIRunnable> mCallback; + +public: + using Base::AttachNative; + using Base::DisposeNative; + + Listener(nsIRunnable* aCallback) : mCallback(aCallback) {} + + void OnFrameAvailable() + { + if (NS_IsMainThread()) { + mCallback->Run(); + return; + } + NS_DispatchToMainThread(mCallback); + } +}; + +already_AddRefed<AndroidSurfaceTexture> +AndroidSurfaceTexture::Create() +{ + return Create(nullptr, 0); +} + +already_AddRefed<AndroidSurfaceTexture> +AndroidSurfaceTexture::Create(GLContext* aContext, GLuint aTexture) +{ + RefPtr<AndroidSurfaceTexture> st = new AndroidSurfaceTexture(); + if (!st->Init(aContext, aTexture)) { + printf_stderr("Failed to initialize AndroidSurfaceTexture"); + st = nullptr; + } + + return st.forget(); +} + +nsresult +AndroidSurfaceTexture::Attach(GLContext* aContext, PRIntervalTime aTimeout) +{ + MonitorAutoLock lock(mMonitor); + + if (mAttachedContext == aContext) { + NS_WARNING("Tried to attach same GLContext to AndroidSurfaceTexture"); + return NS_OK; + } + + if (!CanDetach()) { + return NS_ERROR_NOT_AVAILABLE; + } + + while (mAttachedContext) { + // Wait until it's detached (or we time out) + if (NS_FAILED(lock.Wait(aTimeout))) { + return NS_ERROR_NOT_AVAILABLE; + } + } + + MOZ_ASSERT(aContext->IsOwningThreadCurrent(), "Trying to attach GLContext from different thread"); + + aContext->fGenTextures(1, &mTexture); + + if (NS_FAILED(mSurfaceTexture->AttachToGLContext(mTexture))) { + return NS_ERROR_NOT_AVAILABLE; + } + mAttachedContext = aContext; + mAttachedContext->MakeCurrent(); + + return NS_OK; +} + +nsresult +AndroidSurfaceTexture::Detach() +{ + MonitorAutoLock lock(mMonitor); + + if (!CanDetach() || + !mAttachedContext || + !mAttachedContext->IsOwningThreadCurrent()) + { + return NS_ERROR_FAILURE; + } + + mAttachedContext->MakeCurrent(); + + mSurfaceTexture->DetachFromGLContext(); + + mTexture = 0; + mAttachedContext = nullptr; + lock.NotifyAll(); + return NS_OK; +} + +bool +AndroidSurfaceTexture::CanDetach() const +{ + // The API for attach/detach only exists on 16+, and PowerVR has some sort of + // fencing issue. Additionally, attach/detach seems to be busted on at least + // some Mali adapters (400MP2 for sure, bug 1131793) + return AndroidBridge::Bridge()->GetAPIVersion() >= 16 && + (!mAttachedContext || mAttachedContext->Vendor() != GLVendor::Imagination) && + (!mAttachedContext || mAttachedContext->Vendor() != GLVendor::ARM /* Mali */) && + gfxPrefs::SurfaceTextureDetachEnabled(); +} + +bool +AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture) +{ + + if (!aTexture && !CanDetach()) { + // We have no texture and cannot initialize detached, bail out + return false; + } + + if (NS_WARN_IF(NS_FAILED( + java::sdk::SurfaceTexture::New(aTexture, ReturnTo(&mSurfaceTexture))))) { + return false; + } + + if (!aTexture) { + mSurfaceTexture->DetachFromGLContext(); + } + + mAttachedContext = aContext; + + if (NS_WARN_IF(NS_FAILED( + java::sdk::Surface::New(mSurfaceTexture, ReturnTo(&mSurface))))) { + return false; + } + + mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(), + mSurface.Get()); + MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface"); + + return true; +} + +AndroidSurfaceTexture::AndroidSurfaceTexture() + : mTexture(0) + , mSurfaceTexture() + , mSurface() + , mAttachedContext(nullptr) + , mMonitor("AndroidSurfaceTexture") +{ +} + +AndroidSurfaceTexture::~AndroidSurfaceTexture() +{ + if (mSurfaceTexture) { + SetFrameAvailableCallback(nullptr); + mSurfaceTexture = nullptr; + } + + if (mNativeWindow) { + ANativeWindow_release(mNativeWindow); + mNativeWindow = nullptr; + } +} + +void +AndroidSurfaceTexture::UpdateTexImage() +{ + mSurfaceTexture->UpdateTexImage(); +} + +void +AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix) const +{ + JNIEnv* const env = jni::GetEnvForThread(); + + auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16)); + mSurfaceTexture->GetTransformMatrix(jarray); + + jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr); + + aMatrix._11 = array[0]; + aMatrix._12 = array[1]; + aMatrix._13 = array[2]; + aMatrix._14 = array[3]; + + aMatrix._21 = array[4]; + aMatrix._22 = array[5]; + aMatrix._23 = array[6]; + aMatrix._24 = array[7]; + + aMatrix._31 = array[8]; + aMatrix._32 = array[9]; + aMatrix._33 = array[10]; + aMatrix._34 = array[11]; + + aMatrix._41 = array[12]; + aMatrix._42 = array[13]; + aMatrix._43 = array[14]; + aMatrix._44 = array[15]; + + env->ReleaseFloatArrayElements(jarray.Get(), array, 0); +} + +void +AndroidSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable) +{ + java::SurfaceTextureListener::LocalRef newListener; + + if (aRunnable) { + newListener = java::SurfaceTextureListener::New(); + Listener::AttachNative(newListener, MakeUnique<Listener>(aRunnable)); + } + + if (aRunnable || mListener) { + MOZ_ALWAYS_TRUE(NS_SUCCEEDED( + mSurfaceTexture->SetOnFrameAvailableListener(newListener))); + } + + if (mListener) { + Listener::DisposeNative(java::SurfaceTextureListener::LocalRef( + newListener.Env(), mListener)); + } + + mListener = newListener; +} + +void +AndroidSurfaceTexture::SetDefaultSize(mozilla::gfx::IntSize size) +{ + mSurfaceTexture->SetDefaultBufferSize(size.width, size.height); +} + +} // gl +} // mozilla + +#endif // MOZ_WIDGET_ANDROID diff --git a/gfx/gl/AndroidSurfaceTexture.h b/gfx/gl/AndroidSurfaceTexture.h new file mode 100644 index 0000000000..056fab3263 --- /dev/null +++ b/gfx/gl/AndroidSurfaceTexture.h @@ -0,0 +1,107 @@ +/* -*- 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__ +#ifdef MOZ_WIDGET_ANDROID + +#include <jni.h> +#include <android/native_window.h> +#include "nsIRunnable.h" +#include "gfxPlatform.h" +#include "GLDefs.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/MatrixFwd.h" +#include "mozilla/Monitor.h" + +#include "GeneratedJNIWrappers.h" +#include "SurfaceTexture.h" + +namespace mozilla { +namespace gl { + +class GLContext; + +/** + * This class is a wrapper around Android's SurfaceTexture class. + * Usage is pretty much exactly like the Java class, so see + * the Android documentation for details. + */ +class AndroidSurfaceTexture { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidSurfaceTexture) + +public: + + // The SurfaceTexture is created in an attached state. This method requires + // Android Ice Cream Sandwich. + static already_AddRefed<AndroidSurfaceTexture> Create(GLContext* aGLContext, GLuint aTexture); + + // Here the SurfaceTexture will be created in a detached state. You must call + // Attach() with the GLContext you wish to composite with. It must be done + // on the thread where that GLContext is current. This method requires + // Android Jelly Bean. + static already_AddRefed<AndroidSurfaceTexture> Create(); + + // If we are on Jelly Bean, the SurfaceTexture can be detached and reattached + // to allow consumption from different GLContexts. It is recommended to only + // attach while you are consuming in order to allow this. + // + // Only one GLContext may be attached at any given time. If another is already + // attached, we try to wait for it to become detached. + nsresult Attach(GLContext* aContext, PRIntervalTime aTiemout = PR_INTERVAL_NO_TIMEOUT); + + nsresult Detach(); + + // Ability to detach is based on API version (16+), and we also block PowerVR + // since it has some type of fencing problem. Bug 1100126. + bool CanDetach() const; + + GLContext* AttachedContext() const { return mAttachedContext; } + + ANativeWindow* NativeWindow() const { + return mNativeWindow; + } + + // This attaches the updated data to the TEXTURE_EXTERNAL target + void UpdateTexImage(); + + void GetTransformMatrix(mozilla::gfx::Matrix4x4& aMatrix) const; + + void SetDefaultSize(mozilla::gfx::IntSize size); + + // The callback is guaranteed to be called on the main thread even + // if the upstream callback is received on a different thread + void SetFrameAvailableCallback(nsIRunnable* aRunnable); + + GLuint Texture() const { return mTexture; } + const java::sdk::Surface::Ref& JavaSurface() const { return mSurface; } + +private: + class Listener; + + AndroidSurfaceTexture(); + ~AndroidSurfaceTexture(); + + bool Init(GLContext* aContext, GLuint aTexture); + + GLuint mTexture; + java::sdk::SurfaceTexture::GlobalRef mSurfaceTexture; + java::sdk::Surface::GlobalRef mSurface; + java::SurfaceTextureListener::GlobalRef mListener; + + GLContext* mAttachedContext; + + ANativeWindow* mNativeWindow; + + Monitor mMonitor; +}; + +} +} + + +#endif +#endif diff --git a/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp new file mode 100644 index 0000000000..829c201870 --- /dev/null +++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.cpp @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "DecomposeIntoNoRepeatTriangles.h" +#include "gfxMatrix.h" + +namespace mozilla { +namespace gl { + +void +RectTriangles::AppendRectToCoordArray(InfallibleTArray<coord>& array, + GLfloat x0, GLfloat y0, + GLfloat x1, GLfloat y1) +{ + coord* v = array.AppendElements(6); + + v[0].x = x0; v[0].y = y0; + v[1].x = x1; v[1].y = y0; + v[2].x = x0; v[2].y = y1; + v[3].x = x0; v[3].y = y1; + v[4].x = x1; v[4].y = y0; + v[5].x = x1; v[5].y = y1; +} + +void +RectTriangles::addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, + GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1, + bool flip_y /* = false */) +{ + if (flip_y) { + std::swap(ty0, ty1); + } + AppendRectToCoordArray(mVertexCoords, x0, y0, x1, y1); + AppendRectToCoordArray(mTexCoords, tx0, ty0, tx1, ty1); +} + +static GLfloat +WrapTexCoord(GLfloat v) +{ + // This should return values in range [0, 1.0) + return v - floorf(v); +} + +void +DecomposeIntoNoRepeatTriangles(const gfx::IntRect& aTexCoordRect, + const gfx::IntSize& aTexSize, + RectTriangles& aRects, + bool aFlipY /* = false */) +{ + // normalize this + gfx::IntRect tcr(aTexCoordRect); + while (tcr.x >= aTexSize.width) + tcr.x -= aTexSize.width; + while (tcr.y >= aTexSize.height) + tcr.y -= aTexSize.height; + + // Compute top left and bottom right tex coordinates + GLfloat tl[2] = + { GLfloat(tcr.x) / GLfloat(aTexSize.width), + GLfloat(tcr.y) / GLfloat(aTexSize.height) }; + GLfloat br[2] = + { GLfloat(tcr.XMost()) / GLfloat(aTexSize.width), + GLfloat(tcr.YMost()) / GLfloat(aTexSize.height) }; + + // then check if we wrap in either the x or y axis; if we do, + // then also use fmod to figure out the "true" non-wrapping + // texture coordinates. + + bool xwrap = false, ywrap = false; + if (tcr.x < 0 || tcr.x > aTexSize.width || + tcr.XMost() < 0 || tcr.XMost() > aTexSize.width) + { + xwrap = true; + tl[0] = WrapTexCoord(tl[0]); + br[0] = WrapTexCoord(br[0]); + } + + if (tcr.y < 0 || tcr.y > aTexSize.height || + tcr.YMost() < 0 || tcr.YMost() > aTexSize.height) + { + ywrap = true; + tl[1] = WrapTexCoord(tl[1]); + br[1] = WrapTexCoord(br[1]); + } + + NS_ASSERTION(tl[0] >= 0.0f && tl[0] <= 1.0f && + tl[1] >= 0.0f && tl[1] <= 1.0f && + br[0] >= 0.0f && br[0] <= 1.0f && + br[1] >= 0.0f && br[1] <= 1.0f, + "Somehow generated invalid texture coordinates"); + + // If xwrap is false, the texture will be sampled from tl[0] + // .. br[0]. If xwrap is true, then it will be split into tl[0] + // .. 1.0, and 0.0 .. br[0]. Same for the Y axis. The + // destination rectangle is also split appropriately, according + // to the calculated xmid/ymid values. + + // There isn't a 1:1 mapping between tex coords and destination coords; + // when computing midpoints, we have to take that into account. We + // need to map the texture coords, which are (in the wrap case): + // |tl->1| and |0->br| to the |0->1| range of the vertex coords. So + // we have the length (1-tl)+(br) that needs to map into 0->1. + // These are only valid if there is wrap involved, they won't be used + // otherwise. + GLfloat xlen = (1.0f - tl[0]) + br[0]; + GLfloat ylen = (1.0f - tl[1]) + br[1]; + + NS_ASSERTION(!xwrap || xlen > 0.0f, "xlen isn't > 0, what's going on?"); + NS_ASSERTION(!ywrap || ylen > 0.0f, "ylen isn't > 0, what's going on?"); + NS_ASSERTION(aTexCoordRect.width <= aTexSize.width && + aTexCoordRect.height <= aTexSize.height, "tex coord rect would cause tiling!"); + + if (!xwrap && !ywrap) { + aRects.addRect(0.0f, 0.0f, + 1.0f, 1.0f, + tl[0], tl[1], + br[0], br[1], + aFlipY); + } else if (!xwrap && ywrap) { + GLfloat ymid = (1.0f - tl[1]) / ylen; + aRects.addRect(0.0f, 0.0f, + 1.0f, ymid, + tl[0], tl[1], + br[0], 1.0f, + aFlipY); + aRects.addRect(0.0f, ymid, + 1.0f, 1.0f, + tl[0], 0.0f, + br[0], br[1], + aFlipY); + } else if (xwrap && !ywrap) { + GLfloat xmid = (1.0f - tl[0]) / xlen; + aRects.addRect(0.0f, 0.0f, + xmid, 1.0f, + tl[0], tl[1], + 1.0f, br[1], + aFlipY); + aRects.addRect(xmid, 0.0f, + 1.0f, 1.0f, + 0.0f, tl[1], + br[0], br[1], + aFlipY); + } else { + GLfloat xmid = (1.0f - tl[0]) / xlen; + GLfloat ymid = (1.0f - tl[1]) / ylen; + aRects.addRect(0.0f, 0.0f, + xmid, ymid, + tl[0], tl[1], + 1.0f, 1.0f, + aFlipY); + aRects.addRect(xmid, 0.0f, + 1.0f, ymid, + 0.0f, tl[1], + br[0], 1.0f, + aFlipY); + aRects.addRect(0.0f, ymid, + xmid, 1.0f, + tl[0], 0.0f, + 1.0f, br[1], + aFlipY); + aRects.addRect(xmid, ymid, + 1.0f, 1.0f, + 0.0f, 0.0f, + br[0], br[1], + aFlipY); + } +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/DecomposeIntoNoRepeatTriangles.h b/gfx/gl/DecomposeIntoNoRepeatTriangles.h new file mode 100644 index 0000000000..f67d6f93e8 --- /dev/null +++ b/gfx/gl/DecomposeIntoNoRepeatTriangles.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 DecomposeIntoNoRepeatTriangles_h_ +#define DecomposeIntoNoRepeatTriangles_h_ + +#include "GLTypes.h" +#include "nsRect.h" +#include "nsTArray.h" + +namespace mozilla { +namespace gl { + +/** Helper for DecomposeIntoNoRepeatTriangles + */ +class RectTriangles { +public: + typedef struct { GLfloat x,y; } coord; + + // Always pass texture coordinates upright. If you want to flip the + // texture coordinates emitted to the tex_coords array, set flip_y to + // true. + void addRect(GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, + GLfloat tx0, GLfloat ty0, GLfloat tx1, GLfloat ty1, + bool flip_y = false); + + /** + * these return a float pointer to the start of each array respectively. + * Use it for glVertexAttribPointer calls. + * We can return nullptr if we choose to use Vertex Buffer Objects here. + */ + InfallibleTArray<coord>& vertCoords() { + return mVertexCoords; + } + + InfallibleTArray<coord>& texCoords() { + return mTexCoords; + } + + unsigned int elements() { + return mVertexCoords.Length(); + } +private: + // Reserve inline storage for one quad (2 triangles, 3 coords). + AutoTArray<coord, 6> mVertexCoords; + AutoTArray<coord, 6> mTexCoords; + + static void + AppendRectToCoordArray(InfallibleTArray<coord>& array, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1); +}; + +/** + * Decompose drawing the possibly-wrapped aTexCoordRect rectangle + * of a texture of aTexSize into one or more rectangles (represented + * as 2 triangles) and associated tex coordinates, such that + * we don't have to use the REPEAT wrap mode. If aFlipY is true, the + * texture coordinates will be specified vertically flipped. + * + * The resulting triangle vertex coordinates will be in the space of + * (0.0, 0.0) to (1.0, 1.0) -- transform the coordinates appropriately + * if you need a different space. + * + * The resulting vertex coordinates should be drawn using GL_TRIANGLES, + * and rects.numRects * 3 * 6 + */ +void DecomposeIntoNoRepeatTriangles(const gfx::IntRect& aTexCoordRect, + const gfx::IntSize& aTexSize, + RectTriangles& aRects, + bool aFlipY = false); + +} // namespace gl +} // namespace mozilla + +#endif // DecomposeIntoNoRepeatTriangles_h_ diff --git a/gfx/gl/EGLUtils.cpp b/gfx/gl/EGLUtils.cpp new file mode 100644 index 0000000000..bc55d7fb03 --- /dev/null +++ b/gfx/gl/EGLUtils.cpp @@ -0,0 +1,114 @@ +/* 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 "EGLUtils.h" + +#include "GLContextEGL.h" + +namespace mozilla { +namespace gl { + +bool +DoesEGLContextSupportSharingWithEGLImage(GLContext* gl) +{ + return sEGLLibrary.HasKHRImageBase() && + sEGLLibrary.HasKHRImageTexture2D() && + gl->IsExtensionSupported(GLContext::OES_EGL_image); +} + +EGLImage +CreateEGLImage(GLContext* gl, GLuint tex) +{ + MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl)); + + EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex); + EGLContext eglContext = GLContextEGL::Cast(gl)->mContext; + EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(), + eglContext, + LOCAL_EGL_GL_TEXTURE_2D, + clientBuffer, + nullptr); + return image; +} + +//////////////////////////////////////////////////////////////////////// +// EGLImageWrapper + +/*static*/ EGLImageWrapper* +EGLImageWrapper::Create(GLContext* gl, GLuint tex) +{ + MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl)); + + GLLibraryEGL& library = sEGLLibrary; + EGLDisplay display = EGL_DISPLAY(); + EGLContext eglContext = GLContextEGL::Cast(gl)->mContext; + EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex); + EGLImage image = library.fCreateImage(display, + eglContext, + LOCAL_EGL_GL_TEXTURE_2D, + clientBuffer, + nullptr); + if (!image) { +#ifdef DEBUG + printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", + sEGLLibrary.fGetError()); +#endif + return nullptr; + } + + return new EGLImageWrapper(library, display, image); +} + +EGLImageWrapper::~EGLImageWrapper() +{ + mLibrary.fDestroyImage(mDisplay, mImage); +} + +bool +EGLImageWrapper::FenceSync(GLContext* gl) +{ + MOZ_ASSERT(!mSync); + + if (mLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) { + mSync = mLibrary.fCreateSync(mDisplay, + LOCAL_EGL_SYNC_FENCE, + nullptr); + // We need to flush to make sure the sync object enters the command stream; + // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait + // happens on a different thread/context. + gl->fFlush(); + } + + if (!mSync) { + // we failed to create one, so just do a finish + gl->fFinish(); + } + + return true; +} + +bool +EGLImageWrapper::ClientWaitSync() +{ + if (!mSync) { + // if we have no sync object, then we did a Finish() earlier + return true; + } + + // wait at most 1 second; this should really be never/rarely hit + const uint64_t ns_per_ms = 1000 * 1000; + EGLTime timeout = 1000 * ns_per_ms; + + EGLint result = mLibrary.fClientWaitSync(mDisplay, + mSync, + 0, + timeout); + mLibrary.fDestroySync(mDisplay, mSync); + mSync = nullptr; + + return result == LOCAL_EGL_CONDITION_SATISFIED; +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/EGLUtils.h b/gfx/gl/EGLUtils.h new file mode 100644 index 0000000000..71ca01e9cb --- /dev/null +++ b/gfx/gl/EGLUtils.h @@ -0,0 +1,60 @@ +/* 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 EGLUTILS_H_ +#define EGLUTILS_H_ + +#include "GLContextTypes.h" +#include "GLTypes.h" +#include "mozilla/Assertions.h" + +namespace mozilla { +namespace gl { + +class GLLibraryEGL; + +bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl); +EGLImage CreateEGLImage(GLContext* gl, GLuint tex); + +//////////////////////////////////////////////////////////////////////// +// EGLImageWrapper + +class EGLImageWrapper +{ +public: + static EGLImageWrapper* Create(GLContext* gl, GLuint tex); + +private: + GLLibraryEGL& mLibrary; + const EGLDisplay mDisplay; +public: + const EGLImage mImage; +private: + EGLSync mSync; + + EGLImageWrapper(GLLibraryEGL& library, + EGLDisplay display, + EGLImage image) + : mLibrary(library) + , mDisplay(display) + , mImage(image) + , mSync(0) + { + MOZ_ASSERT(mImage); + } + +public: + ~EGLImageWrapper(); + + // Insert a sync point on the given context, which should be the current active + // context. + bool FenceSync(GLContext* gl); + + bool ClientWaitSync(); +}; + +} // namespace gl +} // namespace mozilla + +#endif diff --git a/gfx/gl/ForceDiscreteGPUHelperCGL.h b/gfx/gl/ForceDiscreteGPUHelperCGL.h new file mode 100644 index 0000000000..3b4cb07efa --- /dev/null +++ b/gfx/gl/ForceDiscreteGPUHelperCGL.h @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 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() + { + // 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..cffa5fbe56 --- /dev/null +++ b/gfx/gl/GLBlitHelper.cpp @@ -0,0 +1,1033 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "gfxUtils.h" +#include "GLBlitHelper.h" +#include "GLContext.h" +#include "GLScreenBuffer.h" +#include "ScopedGLHelpers.h" +#include "mozilla/Preferences.h" +#include "ImageContainer.h" +#include "HeapCopyOfStackArray.h" +#include "mozilla/gfx/Matrix.h" +#include "mozilla/UniquePtr.h" + +#ifdef MOZ_WIDGET_ANDROID +#include "AndroidSurfaceTexture.h" +#include "GLImages.h" +#include "GLLibraryEGL.h" +#endif + +#ifdef XP_MACOSX +#include "MacIOSurfaceImage.h" +#include "GLContextCGL.h" +#endif + +using mozilla::layers::PlanarYCbCrImage; +using mozilla::layers::PlanarYCbCrData; + +namespace mozilla { +namespace gl { + +GLBlitHelper::GLBlitHelper(GLContext* gl) + : mGL(gl) + , mTexBlit_Buffer(0) + , mTexBlit_VertShader(0) + , mTex2DBlit_FragShader(0) + , mTex2DRectBlit_FragShader(0) + , mTex2DBlit_Program(0) + , mTex2DRectBlit_Program(0) + , mYFlipLoc(-1) + , mTextureTransformLoc(-1) + , mTexExternalBlit_FragShader(0) + , mTexYUVPlanarBlit_FragShader(0) + , mTexNV12PlanarBlit_FragShader(0) + , mTexExternalBlit_Program(0) + , mTexYUVPlanarBlit_Program(0) + , mTexNV12PlanarBlit_Program(0) + , mFBO(0) + , mSrcTexY(0) + , mSrcTexCb(0) + , mSrcTexCr(0) + , mSrcTexEGL(0) + , mYTexScaleLoc(-1) + , mCbCrTexScaleLoc(-1) + , mYuvColorMatrixLoc(-1) + , mTexWidth(0) + , mTexHeight(0) + , mCurYScale(1.0f) + , mCurCbCrScale(1.0f) +{ +} + +GLBlitHelper::~GLBlitHelper() +{ + if (!mGL->MakeCurrent()) + return; + + DeleteTexBlitProgram(); + + GLuint tex[] = { + mSrcTexY, + mSrcTexCb, + mSrcTexCr, + mSrcTexEGL, + }; + + mSrcTexY = mSrcTexCb = mSrcTexCr = mSrcTexEGL = 0; + mGL->fDeleteTextures(ArrayLength(tex), tex); + + if (mFBO) { + mGL->fDeleteFramebuffers(1, &mFBO); + } + mFBO = 0; +} + +// Allowed to be destructive of state we restore in functions below. +bool +GLBlitHelper::InitTexQuadProgram(BlitType target) +{ + const char kTexBlit_VertShaderSource[] = "\ + #version 100 \n\ + #ifdef GL_ES \n\ + precision mediump float; \n\ + #endif \n\ + attribute vec2 aPosition; \n\ + \n\ + uniform float uYflip; \n\ + varying vec2 vTexCoord; \n\ + \n\ + void main(void) \n\ + { \n\ + vTexCoord = aPosition; \n\ + vTexCoord.y = abs(vTexCoord.y - uYflip); \n\ + vec2 vertPos = aPosition * 2.0 - 1.0; \n\ + gl_Position = vec4(vertPos, 0.0, 1.0); \n\ + } \n\ + "; + + const char kTex2DBlit_FragShaderSource[] = "\ + #version 100 \n\ + #ifdef GL_ES \n\ + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ + precision highp float; \n\ + #else \n\ + precision mediump float; \n\ + #endif \n\ + #endif \n\ + uniform sampler2D uTexUnit; \n\ + \n\ + varying vec2 vTexCoord; \n\ + \n\ + void main(void) \n\ + { \n\ + gl_FragColor = texture2D(uTexUnit, vTexCoord); \n\ + } \n\ + "; + + const char kTex2DRectBlit_FragShaderSource[] = "\ + #version 100 \n\ + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ + precision highp float; \n\ + #else \n\ + precision mediump float; \n\ + #endif \n\ + \n\ + uniform sampler2D uTexUnit; \n\ + uniform vec2 uTexCoordMult; \n\ + \n\ + varying vec2 vTexCoord; \n\ + \n\ + void main(void) \n\ + { \n\ + gl_FragColor = texture2DRect(uTexUnit, \n\ + vTexCoord * uTexCoordMult); \n\ + } \n\ + "; +#ifdef ANDROID /* MOZ_WIDGET_ANDROID */ + const char kTexExternalBlit_FragShaderSource[] = "\ + #version 100 \n\ + #extension GL_OES_EGL_image_external : require \n\ + #ifdef GL_FRAGMENT_PRECISION_HIGH \n\ + precision highp float; \n\ + #else \n\ + precision mediump float; \n\ + #endif \n\ + varying vec2 vTexCoord; \n\ + uniform mat4 uTextureTransform; \n\ + uniform samplerExternalOES uTexUnit; \n\ + \n\ + void main() \n\ + { \n\ + gl_FragColor = texture2D(uTexUnit, \n\ + (uTextureTransform * vec4(vTexCoord, 0.0, 1.0)).xy); \n\ + } \n\ + "; +#endif + /* From Rec601: + [R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16] + [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128] + [B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128] + + For [0,1] instead of [0,255], and to 5 places: + [R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275] + [G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196] + [B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196] + + From Rec709: + [R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16] + [G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128] + [B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128] + + For [0,1] instead of [0,255], and to 5 places: + [R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275] + [G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196] + [B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196] + */ + const char kTexYUVPlanarBlit_FragShaderSource[] = "\ + #version 100 \n\ + #ifdef GL_ES \n\ + precision mediump float; \n\ + #endif \n\ + varying vec2 vTexCoord; \n\ + uniform sampler2D uYTexture; \n\ + uniform sampler2D uCbTexture; \n\ + uniform sampler2D uCrTexture; \n\ + uniform vec2 uYTexScale; \n\ + uniform vec2 uCbCrTexScale; \n\ + uniform mat3 uYuvColorMatrix; \n\ + void main() \n\ + { \n\ + float y = texture2D(uYTexture, vTexCoord * uYTexScale).r; \n\ + float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r; \n\ + float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r; \n\ + y = y - 0.06275; \n\ + cb = cb - 0.50196; \n\ + cr = cr - 0.50196; \n\ + vec3 yuv = vec3(y, cb, cr); \n\ + gl_FragColor.rgb = uYuvColorMatrix * yuv; \n\ + gl_FragColor.a = 1.0; \n\ + } \n\ + "; + +#ifdef XP_MACOSX + const char kTexNV12PlanarBlit_FragShaderSource[] = "\ + #version 100 \n\ + #extension GL_ARB_texture_rectangle : require \n\ + #ifdef GL_ES \n\ + precision mediump float \n\ + #endif \n\ + varying vec2 vTexCoord; \n\ + uniform sampler2DRect uYTexture; \n\ + uniform sampler2DRect uCbCrTexture; \n\ + uniform vec2 uYTexScale; \n\ + uniform vec2 uCbCrTexScale; \n\ + void main() \n\ + { \n\ + float y = texture2DRect(uYTexture, vTexCoord * uYTexScale).r; \n\ + float cb = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).r; \n\ + float cr = texture2DRect(uCbCrTexture, vTexCoord * uCbCrTexScale).a; \n\ + y = (y - 0.06275) * 1.16438; \n\ + cb = cb - 0.50196; \n\ + cr = cr - 0.50196; \n\ + gl_FragColor.r = y + cr * 1.59603; \n\ + gl_FragColor.g = y - 0.81297 * cr - 0.39176 * cb; \n\ + gl_FragColor.b = y + cb * 2.01723; \n\ + gl_FragColor.a = 1.0; \n\ + } \n\ + "; +#endif + + bool success = false; + + GLuint* programPtr; + GLuint* fragShaderPtr; + const char* fragShaderSource; + switch (target) { + case ConvertEGLImage: + case BlitTex2D: + programPtr = &mTex2DBlit_Program; + fragShaderPtr = &mTex2DBlit_FragShader; + fragShaderSource = kTex2DBlit_FragShaderSource; + break; + case BlitTexRect: + programPtr = &mTex2DRectBlit_Program; + fragShaderPtr = &mTex2DRectBlit_FragShader; + fragShaderSource = kTex2DRectBlit_FragShaderSource; + break; +#ifdef ANDROID + case ConvertSurfaceTexture: + case ConvertGralloc: + programPtr = &mTexExternalBlit_Program; + fragShaderPtr = &mTexExternalBlit_FragShader; + fragShaderSource = kTexExternalBlit_FragShaderSource; + break; +#endif + case ConvertPlanarYCbCr: + programPtr = &mTexYUVPlanarBlit_Program; + fragShaderPtr = &mTexYUVPlanarBlit_FragShader; + fragShaderSource = kTexYUVPlanarBlit_FragShaderSource; + break; +#ifdef XP_MACOSX + case ConvertMacIOSurfaceImage: + programPtr = &mTexNV12PlanarBlit_Program; + fragShaderPtr = &mTexNV12PlanarBlit_FragShader; + fragShaderSource = kTexNV12PlanarBlit_FragShaderSource; + break; +#endif + default: + return false; + } + + GLuint& program = *programPtr; + GLuint& fragShader = *fragShaderPtr; + + // Use do-while(false) to let us break on failure + do { + if (program) { + // Already have it... + success = true; + break; + } + + if (!mTexBlit_Buffer) { + + /* CCW tri-strip: + * 2---3 + * | \ | + * 0---1 + */ + GLfloat verts[] = { + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f + }; + HeapCopyOfStackArray<GLfloat> vertsOnHeap(verts); + + MOZ_ASSERT(!mTexBlit_Buffer); + mGL->fGenBuffers(1, &mTexBlit_Buffer); + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer); + + // Make sure we have a sane size. + mGL->fBufferData(LOCAL_GL_ARRAY_BUFFER, vertsOnHeap.ByteLength(), vertsOnHeap.Data(), LOCAL_GL_STATIC_DRAW); + } + + if (!mTexBlit_VertShader) { + + const char* vertShaderSource = kTexBlit_VertShaderSource; + + mTexBlit_VertShader = mGL->fCreateShader(LOCAL_GL_VERTEX_SHADER); + mGL->fShaderSource(mTexBlit_VertShader, 1, &vertShaderSource, nullptr); + mGL->fCompileShader(mTexBlit_VertShader); + } + + MOZ_ASSERT(!fragShader); + fragShader = mGL->fCreateShader(LOCAL_GL_FRAGMENT_SHADER); + mGL->fShaderSource(fragShader, 1, &fragShaderSource, nullptr); + mGL->fCompileShader(fragShader); + + program = mGL->fCreateProgram(); + mGL->fAttachShader(program, mTexBlit_VertShader); + mGL->fAttachShader(program, fragShader); + mGL->fBindAttribLocation(program, 0, "aPosition"); + mGL->fLinkProgram(program); + + if (GLContext::ShouldSpew()) { + GLint status = 0; + mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_COMPILE_STATUS, &status); + if (status != LOCAL_GL_TRUE) { + NS_ERROR("Vert shader compilation failed."); + + GLint length = 0; + mGL->fGetShaderiv(mTexBlit_VertShader, LOCAL_GL_INFO_LOG_LENGTH, &length); + if (!length) { + printf_stderr("No shader info log available.\n"); + break; + } + + auto buffer = MakeUnique<char[]>(length); + mGL->fGetShaderInfoLog(mTexBlit_VertShader, length, nullptr, buffer.get()); + + printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get()); + break; + } + + status = 0; + mGL->fGetShaderiv(fragShader, LOCAL_GL_COMPILE_STATUS, &status); + if (status != LOCAL_GL_TRUE) { + NS_ERROR("Frag shader compilation failed."); + + GLint length = 0; + mGL->fGetShaderiv(fragShader, LOCAL_GL_INFO_LOG_LENGTH, &length); + if (!length) { + printf_stderr("No shader info log available.\n"); + break; + } + + auto buffer = MakeUnique<char[]>(length); + mGL->fGetShaderInfoLog(fragShader, length, nullptr, buffer.get()); + + printf_stderr("Shader info log (%d bytes): %s\n", length, buffer.get()); + break; + } + } + + GLint status = 0; + mGL->fGetProgramiv(program, LOCAL_GL_LINK_STATUS, &status); + if (status != LOCAL_GL_TRUE) { + if (GLContext::ShouldSpew()) { + NS_ERROR("Linking blit program failed."); + GLint length = 0; + mGL->fGetProgramiv(program, LOCAL_GL_INFO_LOG_LENGTH, &length); + if (!length) { + printf_stderr("No program info log available.\n"); + break; + } + + auto buffer = MakeUnique<char[]>(length); + mGL->fGetProgramInfoLog(program, length, nullptr, buffer.get()); + + printf_stderr("Program info log (%d bytes): %s\n", length, buffer.get()); + } + break; + } + + // Cache and set attribute and uniform + mGL->fUseProgram(program); + switch (target) { +#ifdef ANDROID + case ConvertSurfaceTexture: + case ConvertGralloc: +#endif + case BlitTex2D: + case BlitTexRect: + case ConvertEGLImage: { + GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit"); + MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found"); + mGL->fUniform1i(texUnitLoc, 0); + break; + } + case ConvertPlanarYCbCr: { + GLint texY = mGL->fGetUniformLocation(program, "uYTexture"); + GLint texCb = mGL->fGetUniformLocation(program, "uCbTexture"); + GLint texCr = mGL->fGetUniformLocation(program, "uCrTexture"); + mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale"); + mCbCrTexScaleLoc = mGL->fGetUniformLocation(program, "uCbCrTexScale"); + mYuvColorMatrixLoc = mGL->fGetUniformLocation(program, "uYuvColorMatrix"); + + DebugOnly<bool> hasUniformLocations = texY != -1 && + texCb != -1 && + texCr != -1 && + mYTexScaleLoc != -1 && + mCbCrTexScaleLoc != -1 && + mYuvColorMatrixLoc != -1; + MOZ_ASSERT(hasUniformLocations, "uniforms not found"); + + mGL->fUniform1i(texY, Channel_Y); + mGL->fUniform1i(texCb, Channel_Cb); + mGL->fUniform1i(texCr, Channel_Cr); + break; + } + case ConvertMacIOSurfaceImage: { +#ifdef XP_MACOSX + GLint texY = mGL->fGetUniformLocation(program, "uYTexture"); + GLint texCbCr = mGL->fGetUniformLocation(program, "uCbCrTexture"); + mYTexScaleLoc = mGL->fGetUniformLocation(program, "uYTexScale"); + mCbCrTexScaleLoc= mGL->fGetUniformLocation(program, "uCbCrTexScale"); + + DebugOnly<bool> hasUniformLocations = texY != -1 && + texCbCr != -1 && + mYTexScaleLoc != -1 && + mCbCrTexScaleLoc != -1; + MOZ_ASSERT(hasUniformLocations, "uniforms not found"); + + mGL->fUniform1i(texY, Channel_Y); + mGL->fUniform1i(texCbCr, Channel_Cb); +#endif + break; + } + default: + return false; + } + MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0); + mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip"); + MOZ_ASSERT(mYFlipLoc != -1, "uniform: uYflip not found"); + mTextureTransformLoc = mGL->fGetUniformLocation(program, "uTextureTransform"); + if (mTextureTransformLoc >= 0) { + // Set identity matrix as default + gfx::Matrix4x4 identity; + mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &identity._11); + } + success = true; + } while (false); + + if (!success) { + // Clean up: + DeleteTexBlitProgram(); + return false; + } + + mGL->fUseProgram(program); + mGL->fEnableVertexAttribArray(0); + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mTexBlit_Buffer); + mGL->fVertexAttribPointer(0, + 2, + LOCAL_GL_FLOAT, + false, + 0, + nullptr); + return true; +} + +bool +GLBlitHelper::UseTexQuadProgram(BlitType target, const gfx::IntSize& srcSize) +{ + if (!InitTexQuadProgram(target)) { + return false; + } + + if (target == BlitTexRect) { + GLint texCoordMultLoc = mGL->fGetUniformLocation(mTex2DRectBlit_Program, "uTexCoordMult"); + MOZ_ASSERT(texCoordMultLoc != -1, "uniform not found"); + mGL->fUniform2f(texCoordMultLoc, srcSize.width, srcSize.height); + } + + return true; +} + +void +GLBlitHelper::DeleteTexBlitProgram() +{ + if (mTexBlit_Buffer) { + mGL->fDeleteBuffers(1, &mTexBlit_Buffer); + mTexBlit_Buffer = 0; + } + if (mTexBlit_VertShader) { + mGL->fDeleteShader(mTexBlit_VertShader); + mTexBlit_VertShader = 0; + } + if (mTex2DBlit_FragShader) { + mGL->fDeleteShader(mTex2DBlit_FragShader); + mTex2DBlit_FragShader = 0; + } + if (mTex2DRectBlit_FragShader) { + mGL->fDeleteShader(mTex2DRectBlit_FragShader); + mTex2DRectBlit_FragShader = 0; + } + if (mTex2DBlit_Program) { + mGL->fDeleteProgram(mTex2DBlit_Program); + mTex2DBlit_Program = 0; + } + if (mTex2DRectBlit_Program) { + mGL->fDeleteProgram(mTex2DRectBlit_Program); + mTex2DRectBlit_Program = 0; + } + if (mTexExternalBlit_FragShader) { + mGL->fDeleteShader(mTexExternalBlit_FragShader); + mTexExternalBlit_FragShader = 0; + } + if (mTexYUVPlanarBlit_FragShader) { + mGL->fDeleteShader(mTexYUVPlanarBlit_FragShader); + mTexYUVPlanarBlit_FragShader = 0; + } + if (mTexNV12PlanarBlit_FragShader) { + mGL->fDeleteShader(mTexNV12PlanarBlit_FragShader); + mTexNV12PlanarBlit_FragShader = 0; + } + if (mTexExternalBlit_Program) { + mGL->fDeleteProgram(mTexExternalBlit_Program); + mTexExternalBlit_Program = 0; + } + if (mTexYUVPlanarBlit_Program) { + mGL->fDeleteProgram(mTexYUVPlanarBlit_Program); + mTexYUVPlanarBlit_Program = 0; + } + if (mTexNV12PlanarBlit_Program) { + mGL->fDeleteProgram(mTexNV12PlanarBlit_Program); + mTexNV12PlanarBlit_Program = 0; + } +} + +void +GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + bool internalFBs) +{ + MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB)); + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); + + MOZ_ASSERT(mGL->IsSupported(GLFeature::framebuffer_blit)); + + ScopedBindFramebuffer boundFB(mGL); + ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); + + if (internalFBs) { + mGL->Screen()->BindReadFB_Internal(srcFB); + mGL->Screen()->BindDrawFB_Internal(destFB); + } else { + mGL->BindReadFB(srcFB); + mGL->BindDrawFB(destFB); + } + + mGL->fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, + 0, 0, destSize.width, destSize.height, + LOCAL_GL_COLOR_BUFFER_BIT, + LOCAL_GL_NEAREST); +} + +void +GLBlitHelper::BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + const GLFormats& srcFormats, + bool internalFBs) +{ + MOZ_ASSERT(!srcFB || mGL->fIsFramebuffer(srcFB)); + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); + + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + BlitFramebufferToFramebuffer(srcFB, destFB, + srcSize, destSize, + internalFBs); + return; + } + + GLuint tex = CreateTextureForOffscreen(mGL, srcFormats, srcSize); + MOZ_ASSERT(tex); + + BlitFramebufferToTexture(srcFB, tex, srcSize, srcSize, internalFBs); + BlitTextureToFramebuffer(tex, destFB, srcSize, destSize, internalFBs); + + mGL->fDeleteTextures(1, &tex); +} + +void +GLBlitHelper::BindAndUploadYUVTexture(Channel which, + uint32_t width, + uint32_t height, + void* data, + bool needsAllocation) +{ + MOZ_ASSERT(which < Channel_Max, "Invalid channel!"); + GLuint* srcTexArr[3] = {&mSrcTexY, &mSrcTexCb, &mSrcTexCr}; + GLuint& tex = *srcTexArr[which]; + + // 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 format; + GLenum internalFormat; + if (mGL->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) || + mGL->IsAtLeast(gl::ContextProfile::OpenGLES, 300)) { + format = LOCAL_GL_RED; + internalFormat = LOCAL_GL_R8; + } else { + format = LOCAL_GL_LUMINANCE; + internalFormat = LOCAL_GL_LUMINANCE; + } + + if (!tex) { + MOZ_ASSERT(needsAllocation); + tex = CreateTexture(mGL, internalFormat, format, LOCAL_GL_UNSIGNED_BYTE, + gfx::IntSize(width, height), false); + } + mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + which); + + mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, tex); + if (!needsAllocation) { + mGL->fTexSubImage2D(LOCAL_GL_TEXTURE_2D, + 0, + 0, + 0, + width, + height, + format, + LOCAL_GL_UNSIGNED_BYTE, + data); + } else { + mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + internalFormat, + width, + height, + 0, + format, + LOCAL_GL_UNSIGNED_BYTE, + data); + } +} + +void +GLBlitHelper::BindAndUploadEGLImage(EGLImage image, GLuint target) +{ + MOZ_ASSERT(image != EGL_NO_IMAGE, "Bad EGLImage"); + + if (!mSrcTexEGL) { + mGL->fGenTextures(1, &mSrcTexEGL); + mGL->fBindTexture(target, mSrcTexEGL); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); + mGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); + } else { + mGL->fBindTexture(target, mSrcTexEGL); + } + mGL->fEGLImageTargetTexture2D(target, image); +} + +#ifdef MOZ_WIDGET_ANDROID + +#define ATTACH_WAIT_MS 50 + +bool +GLBlitHelper::BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage) +{ + AndroidSurfaceTexture* surfaceTexture = stImage->GetSurfaceTexture(); + + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + + if (NS_FAILED(surfaceTexture->Attach(mGL, PR_MillisecondsToInterval(ATTACH_WAIT_MS)))) + return false; + + // UpdateTexImage() changes the EXTERNAL binding, so save it here + // so we can restore it after. + int oldBinding = 0; + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_EXTERNAL, &oldBinding); + + surfaceTexture->UpdateTexImage(); + + gfx::Matrix4x4 transform; + surfaceTexture->GetTransformMatrix(transform); + + mGL->fUniformMatrix4fv(mTextureTransformLoc, 1, false, &transform._11); + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + + surfaceTexture->Detach(); + + mGL->fBindTexture(LOCAL_GL_TEXTURE_EXTERNAL, oldBinding); + return true; +} + +bool +GLBlitHelper::BlitEGLImageImage(layers::EGLImageImage* image) +{ + EGLImage eglImage = image->GetImage(); + EGLSync eglSync = image->GetSync(); + + if (eglSync) { + EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), eglSync, 0, LOCAL_EGL_FOREVER); + if (status != LOCAL_EGL_CONDITION_SATISFIED) { + return false; + } + } + + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + + int oldBinding = 0; + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldBinding); + + BindAndUploadEGLImage(eglImage, LOCAL_GL_TEXTURE_2D); + + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + + mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldBinding); + return true; +} + +#endif + +bool +GLBlitHelper::BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage) +{ + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + const PlanarYCbCrData* yuvData = yuvImage->GetData(); + + bool needsAllocation = false; + if (mTexWidth != yuvData->mYStride || mTexHeight != yuvData->mYSize.height) { + mTexWidth = yuvData->mYStride; + mTexHeight = yuvData->mYSize.height; + needsAllocation = true; + } + + GLint oldTex[3]; + for (int i = 0; i < 3; i++) { + mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i); + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]); + } + BindAndUploadYUVTexture(Channel_Y, yuvData->mYStride, yuvData->mYSize.height, yuvData->mYChannel, needsAllocation); + BindAndUploadYUVTexture(Channel_Cb, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCbChannel, needsAllocation); + BindAndUploadYUVTexture(Channel_Cr, yuvData->mCbCrStride, yuvData->mCbCrSize.height, yuvData->mCrChannel, needsAllocation); + + if (needsAllocation) { + mGL->fUniform2f(mYTexScaleLoc, (float)yuvData->mYSize.width/yuvData->mYStride, 1.0f); + mGL->fUniform2f(mCbCrTexScaleLoc, (float)yuvData->mCbCrSize.width/yuvData->mCbCrStride, 1.0f); + } + + float* yuvToRgb = gfxUtils::Get3x3YuvColorMatrix(yuvData->mYUVColorSpace); + mGL->fUniformMatrix3fv(mYuvColorMatrixLoc, 1, 0, yuvToRgb); + + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + for (int i = 0; i < 3; i++) { + mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i); + mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]); + } + return true; +} + +#ifdef XP_MACOSX +bool +GLBlitHelper::BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage) +{ + ScopedBindTextureUnit boundTU(mGL, LOCAL_GL_TEXTURE0); + MacIOSurface* surf = ioImage->GetSurface(); + + GLint oldTex[2]; + for (int i = 0; i < 2; i++) { + mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i); + mGL->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, &oldTex[i]); + } + + GLuint textures[2]; + mGL->fGenTextures(2, textures); + + mGL->fActiveTexture(LOCAL_GL_TEXTURE0); + mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[0]); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 0); + mGL->fUniform2f(mYTexScaleLoc, surf->GetWidth(0), surf->GetHeight(0)); + + mGL->fActiveTexture(LOCAL_GL_TEXTURE1); + mGL->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, textures[1]); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_RECTANGLE_ARB, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + surf->CGLTexImageIOSurface2D(gl::GLContextCGL::Cast(mGL)->GetCGLContext(), 1); + mGL->fUniform2f(mCbCrTexScaleLoc, surf->GetWidth(1), surf->GetHeight(1)); + + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); + for (int i = 0; i < 2; i++) { + mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + i); + mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, oldTex[i]); + } + + mGL->fDeleteTextures(2, textures); + return true; +} +#endif + +bool +GLBlitHelper::BlitImageToFramebuffer(layers::Image* srcImage, + const gfx::IntSize& destSize, + GLuint destFB, + OriginPos destOrigin) +{ + ScopedGLDrawState autoStates(mGL); + + BlitType type; + OriginPos srcOrigin; + + switch (srcImage->GetFormat()) { + case ImageFormat::PLANAR_YCBCR: + type = ConvertPlanarYCbCr; + srcOrigin = OriginPos::BottomLeft; + break; + +#ifdef MOZ_WIDGET_ANDROID + case ImageFormat::SURFACE_TEXTURE: + type = ConvertSurfaceTexture; + srcOrigin = srcImage->AsSurfaceTextureImage()->GetOriginPos(); + break; + case ImageFormat::EGLIMAGE: + type = ConvertEGLImage; + srcOrigin = srcImage->AsEGLImageImage()->GetOriginPos(); + break; +#endif +#ifdef XP_MACOSX + case ImageFormat::MAC_IOSURFACE: + type = ConvertMacIOSurfaceImage; + srcOrigin = OriginPos::TopLeft; + break; +#endif + + default: + return false; + } + + bool init = InitTexQuadProgram(type); + if (!init) { + return false; + } + + const bool needsYFlip = (srcOrigin != destOrigin); + mGL->fUniform1f(mYFlipLoc, needsYFlip ? (float)1.0 : (float)0.0); + + ScopedBindFramebuffer boundFB(mGL, destFB); + mGL->fColorMask(LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE, LOCAL_GL_TRUE); + mGL->fViewport(0, 0, destSize.width, destSize.height); + + switch (type) { + case ConvertPlanarYCbCr: { + const auto saved = mGL->GetIntAs<GLint>(LOCAL_GL_UNPACK_ALIGNMENT); + mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, 1); + const auto ret = BlitPlanarYCbCrImage(static_cast<PlanarYCbCrImage*>(srcImage)); + mGL->fPixelStorei(LOCAL_GL_UNPACK_ALIGNMENT, saved); + return ret; + } + +#ifdef MOZ_WIDGET_ANDROID + case ConvertSurfaceTexture: + return BlitSurfaceTextureImage(static_cast<layers::SurfaceTextureImage*>(srcImage)); + + case ConvertEGLImage: + return BlitEGLImageImage(static_cast<layers::EGLImageImage*>(srcImage)); +#endif + +#ifdef XP_MACOSX + case ConvertMacIOSurfaceImage: + return BlitMacIOSurfaceImage(srcImage->AsMacIOSurfaceImage()); +#endif + + default: + return false; + } +} + +bool +GLBlitHelper::BlitImageToTexture(layers::Image* srcImage, + const gfx::IntSize& destSize, + GLuint destTex, + GLenum destTarget, + OriginPos destOrigin) +{ + ScopedFramebufferForTexture autoFBForTex(mGL, destTex, destTarget); + if (!autoFBForTex.IsComplete()) + return false; + + return BlitImageToFramebuffer(srcImage, destSize, autoFBForTex.FB(), destOrigin); +} + +void +GLBlitHelper::BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum srcTarget, + bool internalFBs) +{ + MOZ_ASSERT(mGL->fIsTexture(srcTex)); + MOZ_ASSERT(!destFB || mGL->fIsFramebuffer(destFB)); + + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget); + MOZ_DIAGNOSTIC_ASSERT(srcWrapper.IsComplete()); + + BlitFramebufferToFramebuffer(srcWrapper.FB(), destFB, + srcSize, destSize, + internalFBs); + return; + } + + DrawBlitTextureToFramebuffer(srcTex, destFB, srcSize, destSize, srcTarget, + internalFBs); +} + + +void +GLBlitHelper::DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum srcTarget, + bool internalFBs) +{ + BlitType type; + switch (srcTarget) { + case LOCAL_GL_TEXTURE_2D: + type = BlitTex2D; + break; + case LOCAL_GL_TEXTURE_RECTANGLE_ARB: + type = BlitTexRect; + break; + default: + MOZ_CRASH("GFX: Fatal Error: Bad `srcTarget`."); + break; + } + + ScopedGLDrawState autoStates(mGL); + if (internalFBs) { + mGL->Screen()->BindFB_Internal(destFB); + } else { + mGL->BindFB(destFB); + } + + // Does destructive things to (only!) what we just saved above. + bool good = UseTexQuadProgram(type, srcSize); + if (!good) { + // We're up against the wall, so bail. + MOZ_DIAGNOSTIC_ASSERT(false, + "Error: Failed to prepare to blit texture->framebuffer.\n"); + mGL->fScissor(0, 0, destSize.width, destSize.height); + mGL->fColorMask(1, 1, 1, 1); + mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); + return; + } + + mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4); +} + +void +GLBlitHelper::BlitFramebufferToTexture(GLuint srcFB, GLuint destTex, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum destTarget, + bool internalFBs) +{ + // On the Android 4.3 emulator, IsFramebuffer may return false incorrectly. + MOZ_ASSERT_IF(mGL->Renderer() != GLRenderer::AndroidEmulator, !srcFB || mGL->fIsFramebuffer(srcFB)); + MOZ_ASSERT(mGL->fIsTexture(destTex)); + + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + ScopedFramebufferForTexture destWrapper(mGL, destTex, destTarget); + + BlitFramebufferToFramebuffer(srcFB, destWrapper.FB(), + srcSize, destSize, + internalFBs); + return; + } + + ScopedBindTexture autoTex(mGL, destTex, destTarget); + + ScopedBindFramebuffer boundFB(mGL); + if (internalFBs) { + mGL->Screen()->BindFB_Internal(srcFB); + } else { + mGL->BindFB(srcFB); + } + + 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) +{ + MOZ_ASSERT(mGL->fIsTexture(srcTex)); + MOZ_ASSERT(mGL->fIsTexture(destTex)); + + // Generally, just use the CopyTexSubImage path + ScopedFramebufferForTexture srcWrapper(mGL, srcTex, srcTarget); + + BlitFramebufferToTexture(srcWrapper.FB(), destTex, + srcSize, destSize, destTarget); +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/GLBlitHelper.h b/gfx/gl/GLBlitHelper.h new file mode 100644 index 0000000000..31d6a2f5b1 --- /dev/null +++ b/gfx/gl/GLBlitHelper.h @@ -0,0 +1,168 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "GLContextTypes.h" +#include "GLConsts.h" +#include "nsSize.h" +#include "mozilla/Attributes.h" +#include "mozilla/gfx/Point.h" + +namespace mozilla { + +namespace layers { +class Image; +class PlanarYCbCrImage; +class GrallocImage; +class SurfaceTextureImage; +class MacIOSurfaceImage; +class EGLImageImage; +} // namespace layers + +namespace gl { + +class GLContext; + +/** Buffer blitting helper */ +class GLBlitHelper final +{ + enum Channel + { + Channel_Y = 0, + Channel_Cb, + Channel_Cr, + Channel_Max, + }; + + /** + * BlitTex2D is used to copy blit the content of a GL_TEXTURE_2D object, + * BlitTexRect is used to copy blit the content of a GL_TEXTURE_RECT object, + * The difference between BlitTex2D and BlitTexRect is the texture type, which affect + * the fragment shader a bit. + * + * ConvertGralloc is used to color convert copy blit the GrallocImage into a + * normal RGB texture by egl_image_external extension + * ConvertPlnarYcbCr is used to color convert copy blit the PlanarYCbCrImage + * into a normal RGB texture by create textures of each color channel, and + * convert it in GPU. + * Convert type is created for canvas. + */ + enum BlitType + { + BlitTex2D, + BlitTexRect, + ConvertGralloc, + ConvertPlanarYCbCr, + ConvertSurfaceTexture, + ConvertEGLImage, + ConvertMacIOSurfaceImage + }; + // The GLContext is the sole owner of the GLBlitHelper. + GLContext* mGL; + + GLuint mTexBlit_Buffer; + GLuint mTexBlit_VertShader; + GLuint mTex2DBlit_FragShader; + GLuint mTex2DRectBlit_FragShader; + GLuint mTex2DBlit_Program; + GLuint mTex2DRectBlit_Program; + + GLint mYFlipLoc; + + GLint mTextureTransformLoc; + + // Data for image blit path + GLuint mTexExternalBlit_FragShader; + GLuint mTexYUVPlanarBlit_FragShader; + GLuint mTexNV12PlanarBlit_FragShader; + GLuint mTexExternalBlit_Program; + GLuint mTexYUVPlanarBlit_Program; + GLuint mTexNV12PlanarBlit_Program; + GLuint mFBO; + GLuint mSrcTexY; + GLuint mSrcTexCb; + GLuint mSrcTexCr; + GLuint mSrcTexEGL; + GLint mYTexScaleLoc; + GLint mCbCrTexScaleLoc; + GLint mYuvColorMatrixLoc; + int mTexWidth; + int mTexHeight; + + // Cache some uniform values + float mCurYScale; + float mCurCbCrScale; + + void UseBlitProgram(); + void SetBlitFramebufferForDestTexture(GLuint aTexture); + + bool UseTexQuadProgram(BlitType target, const gfx::IntSize& srcSize); + bool InitTexQuadProgram(BlitType target = BlitTex2D); + void DeleteTexBlitProgram(); + void BindAndUploadYUVTexture(Channel which, uint32_t width, uint32_t height, void* data, bool allocation); + void BindAndUploadEGLImage(EGLImage image, GLuint target); + + bool BlitPlanarYCbCrImage(layers::PlanarYCbCrImage* yuvImage); +#ifdef MOZ_WIDGET_ANDROID + // Blit onto the current FB. + bool BlitSurfaceTextureImage(layers::SurfaceTextureImage* stImage); + bool BlitEGLImageImage(layers::EGLImageImage* eglImage); +#endif +#ifdef XP_MACOSX + bool BlitMacIOSurfaceImage(layers::MacIOSurfaceImage* ioImage); +#endif + + explicit GLBlitHelper(GLContext* gl); + + friend class GLContext; + +public: + ~GLBlitHelper(); + + // If you don't have |srcFormats| for the 2nd definition, + // then you'll need the framebuffer_blit extensions to use + // the first BlitFramebufferToFramebuffer. + void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + bool internalFBs = false); + void BlitFramebufferToFramebuffer(GLuint srcFB, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + const GLFormats& srcFormats, + bool internalFBs = false); + void BlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum srcTarget = LOCAL_GL_TEXTURE_2D, + bool internalFBs = false); + void DrawBlitTextureToFramebuffer(GLuint srcTex, GLuint destFB, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum srcTarget = LOCAL_GL_TEXTURE_2D, + bool internalFBs = false); + void BlitFramebufferToTexture(GLuint srcFB, GLuint destTex, + const gfx::IntSize& srcSize, + const gfx::IntSize& destSize, + GLenum destTarget = LOCAL_GL_TEXTURE_2D, + bool internalFBs = false); + 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); + bool BlitImageToFramebuffer(layers::Image* srcImage, const gfx::IntSize& destSize, + GLuint destFB, OriginPos destOrigin); + bool BlitImageToTexture(layers::Image* srcImage, const gfx::IntSize& destSize, + GLuint destTex, GLenum destTarget, OriginPos destOrigin); +}; + +} // namespace gl +} // namespace mozilla + +#endif // GLBLITHELPER_H_ diff --git a/gfx/gl/GLConsts.h b/gfx/gl/GLConsts.h new file mode 100644 index 0000000000..ad6175e163 --- /dev/null +++ b/gfx/gl/GLConsts.h @@ -0,0 +1,5951 @@ +/* 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 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 'GLParseRegistryXML.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_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_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_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_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_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_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_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_SHADERS 0x8B85 +#define LOCAL_GL_ATTENUATION_EXT 0x834D +#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_BLEND 0x0BE2 +#define LOCAL_GL_BLEND_ADVANCED_COHERENT_NV 0x9285 +#define LOCAL_GL_BLEND_COLOR 0x8005 +#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_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_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_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_NV 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_PIXEL_STORE_BIT 0x00000001 +#define LOCAL_GL_CLIENT_STORAGE_BIT 0x0200 +#define LOCAL_GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define LOCAL_GL_CLIP_DISTANCE0 0x3000 +#define LOCAL_GL_CLIP_DISTANCE1 0x3001 +#define LOCAL_GL_CLIP_DISTANCE2 0x3002 +#define LOCAL_GL_CLIP_DISTANCE3 0x3003 +#define LOCAL_GL_CLIP_DISTANCE4 0x3004 +#define LOCAL_GL_CLIP_DISTANCE5 0x3005 +#define LOCAL_GL_CLIP_DISTANCE6 0x3006 +#define LOCAL_GL_CLIP_DISTANCE7 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_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_NV 0x929A +#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_ATTACHMENT1_EXT 0x8CE1 +#define LOCAL_GL_COLOR_ATTACHMENT1_NV 0x8CE1 +#define LOCAL_GL_COLOR_ATTACHMENT2 0x8CE2 +#define LOCAL_GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define LOCAL_GL_COLOR_ATTACHMENT2_NV 0x8CE2 +#define LOCAL_GL_COLOR_ATTACHMENT3 0x8CE3 +#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_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_KHR 0x93BB +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#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_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_KHR 0x93B1 +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4 +#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_KHR 0x93B3 +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7 +#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_KHR 0x93B5 +#define LOCAL_GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#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_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_UNSIGNED_FLOAT 0x8E8F +#define LOCAL_GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 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_KHR 0x93DB +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#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_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_KHR 0x93D1 +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4 +#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_KHR 0x93D3 +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7 +#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_KHR 0x93D5 +#define LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#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_EXT 0x8C49 +#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 +#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 +#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_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_CONJOINT_NV 0x9284 +#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_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_ROBUST_ACCESS_BIT_ARB 0x00000004 +#define LOCAL_GL_CONTEXT_PROFILE_MASK 0x9126 +#define LOCAL_GL_CONTEXT_ROBUST_ACCESS_EXT 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_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_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_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_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_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_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_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_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_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_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_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_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_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_EIGHTH_BIT_ATI 0x00000020 +#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_NV 0x92A0 +#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_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_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_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_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_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_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_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_UNDERLINE_POSITION_BIT_NV 0x04000000 +#define LOCAL_GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 +#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_FRACTIONAL_EVEN 0x8E7C +#define LOCAL_GL_FRACTIONAL_ODD 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_DEPTH 0x8452 +#define LOCAL_GL_FRAGMENT_DEPTH_EXT 0x8452 +#define LOCAL_GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 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_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_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_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_SAMPLES_EXT 0x8D6C +#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_SAMPLES 0x9313 +#define LOCAL_GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define LOCAL_GL_FRAMEBUFFER_EXT 0x8D40 +#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_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_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_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_OES 0x8D40 +#define LOCAL_GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define LOCAL_GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#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_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_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_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_EXT 0x8DD9 +#define LOCAL_GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#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_GUILTY_CONTEXT_RESET_ARB 0x8253 +#define LOCAL_GL_GUILTY_CONTEXT_RESET_EXT 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_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_NV 0x92AF +#define LOCAL_GL_HSL_HUE_NV 0x92AD +#define LOCAL_GL_HSL_LUMINOSITY_NV 0x92B0 +#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_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_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_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_ARB 0x8254 +#define LOCAL_GL_INNOCENT_CONTEXT_RESET_EXT 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_NV 0x140E +#define LOCAL_GL_INT64_VEC2_NV 0x8FE9 +#define LOCAL_GL_INT64_VEC3_NV 0x8FEA +#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_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_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_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_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_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_IS_PER_PATCH 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_VIDEO_CAPTURE_STATUS_NV 0x9027 +#define LOCAL_GL_LAYER_NV 0x8DAA +#define LOCAL_GL_LAYER_PROVOKING_VERTEX 0x825E +#define LOCAL_GL_LAYOUT_DEFAULT_INTEL 0 +#define LOCAL_GL_LAYOUT_LINEAR_CPU_CACHED_INTEL 2 +#define LOCAL_GL_LAYOUT_LINEAR_INTEL 1 +#define LOCAL_GL_LEFT 0x0406 +#define LOCAL_GL_LEQUAL 0x0203 +#define LOCAL_GL_LERP_ATI 0x8969 +#define LOCAL_GL_LESS 0x0201 +#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_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_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_LINE_BIT 0x00000004 +#define LOCAL_GL_LINE_LOOP 0x0002 +#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_TOKEN 0x0702 +#define LOCAL_GL_LINE_TO_NV 0x04 +#define LOCAL_GL_LINE_WIDTH 0x0B21 +#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_LOGIC_OP 0x0BF1 +#define LOCAL_GL_LOGIC_OP_MODE 0x0BF0 +#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#define LOCAL_GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 +#define LOCAL_GL_LOWER_LEFT 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_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_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_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_PLANES 0x0D32 +#define LOCAL_GL_MAX_CLIP_PLANES_IMG 0x0D32 +#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_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_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_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_SHADER_OUTPUT_RESOURCES 0x8F39 +#define LOCAL_GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 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_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_TEXTURE_SAMPLES 0x910F +#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_DUAL_SOURCE_DRAW_BUFFERS 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_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_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_COUNTER_BUFFERS 0x92CF +#define LOCAL_GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT 0x8DE4 +#define LOCAL_GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define LOCAL_GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define LOCAL_GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 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_PROGRAM_INVOCATIONS_NV 0x8E5A +#define LOCAL_GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define LOCAL_GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 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_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_UNIFORM_BLOCKS 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_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_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_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_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_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_STORAGE_BLOCK_SIZE 0x90DE +#define LOCAL_GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#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_ARRAY_TEXTURE_LAYERS 0x919A +#define LOCAL_GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A +#define LOCAL_GL_MAX_SPARSE_TEXTURE_SIZE_AMD 0x9198 +#define LOCAL_GL_MAX_SPARSE_TEXTURE_SIZE_ARB 0x9198 +#define LOCAL_GL_MAX_SPOT_EXPONENT_NV 0x8505 +#define LOCAL_GL_MAX_SUBROUTINES 0x8DE7 +#define LOCAL_GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define LOCAL_GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define LOCAL_GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define LOCAL_GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define LOCAL_GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define LOCAL_GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define LOCAL_GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define LOCAL_GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define LOCAL_GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define LOCAL_GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define LOCAL_GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define LOCAL_GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define LOCAL_GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define LOCAL_GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define LOCAL_GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define LOCAL_GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define LOCAL_GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define LOCAL_GL_MAX_TESS_PATCH_COMPONENTS 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_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_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_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_VIEWPORT_DIMS 0x0D3A +#define LOCAL_GL_MAX_WIDTH 0x827E +#define LOCAL_GL_MEDIUM_FLOAT 0x8DF1 +#define LOCAL_GL_MEDIUM_INT 0x8DF4 +#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_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_SPARSE_LEVEL_AMD 0x919B +#define LOCAL_GL_MIN_SPARSE_LEVEL_ARB 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_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_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_MULTIPLY_NV 0x9294 +#define LOCAL_GL_MULTISAMPLE 0x809D +#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_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_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_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_ARB 0x8261 +#define LOCAL_GL_NO_RESET_NOTIFICATION_EXT 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_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_VIDEO_CAPTURE_STREAMS_NV 0x9024 +#define LOCAL_GL_NUM_VIRTUAL_PAGE_SIZES_ARB 0x91A8 +#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_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_COLOR 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_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_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 0x842C +#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_ARB 0x80EE +#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_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define LOCAL_GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define LOCAL_GL_PATCH_VERTICES 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_MITER_LIMIT_NV 0x907A +#define LOCAL_GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A +#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_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_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_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_EXT 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_EXT 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_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_OFFSET_BIAS_EXT 0x8039 +#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_POINT 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_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_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_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_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_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_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_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_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C +#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_NV 0x8E16 +#define LOCAL_GL_QUERY_BY_REGION_WAIT 0x8E15 +#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_NV 0x8E14 +#define LOCAL_GL_QUERY_OBJECT_AMD 0x9153 +#define LOCAL_GL_QUERY_OBJECT_EXT 0x9153 +#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_WAIT 0x8E13 +#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_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_SNORM 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_POSITION_UNCLIPPED_IBM 0x19262 +#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_TESS_CONTROL_SHADER 0x9307 +#define LOCAL_GL_REFERENCED_BY_TESS_EVALUATION_SHADER 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_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_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_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_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_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 0x842E +#define LOCAL_GL_RESAMPLE_ZERO_FILL_OML 0x8987 +#define LOCAL_GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define LOCAL_GL_RESCALE_NORMAL 0x803A +#define LOCAL_GL_RESCALE_NORMAL_EXT 0x803A +#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define LOCAL_GL_RESET_NOTIFICATION_STRATEGY_EXT 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_SNORM 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_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_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_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_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_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_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_SHADOW 0x900D +#define LOCAL_GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 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_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_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_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_TEST 0x0C11 +#define LOCAL_GL_SCREEN_COORDINATES_REND 0x8490 +#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_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_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_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_SHADOW_AMBIENT_SGIX 0x80BF +#define LOCAL_GL_SHADOW_ATTENUATION_EXT 0x834E +#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_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_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_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9 +#define LOCAL_GL_SPECULAR 0x1202 +#define LOCAL_GL_SPHERE_MAP 0x2402 +#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_SRC0_ALPHA 0x8588 +#define LOCAL_GL_SRC0_RGB 0x8580 +#define LOCAL_GL_SRC1_ALPHA 0x8589 +#define LOCAL_GL_SRC1_COLOR 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_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_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_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_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_RENDERABLE 0x8288 +#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_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_SUBPIXEL_BITS 0x0D50 +#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_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_TESSELLATION_FACTOR_AMD 0x9005 +#define LOCAL_GL_TESSELLATION_MODE_AMD 0x9004 +#define LOCAL_GL_TESS_CONTROL_OUTPUT_VERTICES 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_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_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_POINT_MODE 0x8E79 +#define LOCAL_GL_TESS_GEN_SPACING 0x8E77 +#define LOCAL_GL_TESS_GEN_VERTEX_ORDER 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_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_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_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_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_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_NV 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_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_EXT 0x8C2A +#define LOCAL_GL_TEXTURE_BUFFER_FORMAT_ARB 0x8C2E +#define LOCAL_GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E +#define LOCAL_GL_TEXTURE_BUFFER_OFFSET 0x919D +#define LOCAL_GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define LOCAL_GL_TEXTURE_BUFFER_SIZE 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_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_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_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_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_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_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_QCOM 0x8BDA +#define LOCAL_GL_TEXTURE_TOO_LARGE_EXT 0x8065 +#define LOCAL_GL_TEXTURE_TYPE_QCOM 0x8BD7 +#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_LEVEL 0x82DB +#define LOCAL_GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define LOCAL_GL_TEXTURE_VIEW_NUM_LEVELS 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_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_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_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_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_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_UNIFORM 0x92E1 +#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_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_BINDING 0x8A28 +#define LOCAL_GL_UNIFORM_BUFFER_BINDING_EXT 0x8DEF +#define LOCAL_GL_UNIFORM_BUFFER_EXT 0x8DEE +#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_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_ARB 0x8255 +#define LOCAL_GL_UNKNOWN_CONTEXT_RESET_EXT 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_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_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_RESAMPLE_OML 0x8985 +#define LOCAL_GL_UNPACK_RESAMPLE_SGIX 0x842D +#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_NV 0x8FF5 +#define LOCAL_GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 +#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_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_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_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_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_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_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_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_UPPER_LEFT 0x8CA2 +#define LOCAL_GL_USE_MISSING_GLYPH_NV 0x90AA +#define LOCAL_GL_UTF16_NV 0x909B +#define LOCAL_GL_UTF8_NV 0x909A +#define LOCAL_GL_V2F 0x2A20 +#define LOCAL_GL_V3F 0x2A21 +#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_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_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_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_INDEX_PROVOKING_VERTEX 0x825F +#define LOCAL_GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#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_BPTC_FLOAT 0x82D3 +#define LOCAL_GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#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_X_AMD 0x9195 +#define LOCAL_GL_VIRTUAL_PAGE_SIZE_X_ARB 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_Z_AMD 0x9197 +#define LOCAL_GL_VIRTUAL_PAGE_SIZE_Z_ARB 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_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_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_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_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_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_BUFFER_AGE_EXT 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_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_FORMAT_HI 0x8F70 +#define LOCAL_EGL_COLOR_RGBA_HI 0x8F72 +#define LOCAL_EGL_COLOR_RGB_HI 0x8F71 +#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_CONFORMANT 0x3042 +#define LOCAL_EGL_CONFORMANT_KHR 0x3042 +#define LOCAL_EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E +#define LOCAL_EGL_CONSUMER_FRAME_KHR 0x3213 +#define LOCAL_EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 +#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_KHR 0x3098 +#define LOCAL_EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define LOCAL_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define LOCAL_EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#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_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_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_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#define LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2 +#define LOCAL_EGL_DEFAULT_DISPLAY ((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_DISCARD_SAMPLES_ARM 0x3286 +#define LOCAL_EGL_DISPLAY_SCALING 10000 +#define LOCAL_EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#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_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_OFFSET_EXT 0x3279 +#define LOCAL_EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define LOCAL_EGL_DONT_CARE ((EGLint)-1) +#define LOCAL_EGL_DRAW 0x3059 +#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_MESA 0x31D1 +#define LOCAL_EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 +#define LOCAL_EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 +#define LOCAL_EGL_EXTENSIONS 0x3055 +#define LOCAL_EGL_FALSE 0 +#define LOCAL_EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFF +#define LOCAL_EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFF +#define LOCAL_EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 +#define LOCAL_EGL_FORMAT_RGBA_8888_KHR 0x30C3 +#define LOCAL_EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 +#define LOCAL_EGL_FORMAT_RGB_565_KHR 0x30C1 +#define LOCAL_EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#define LOCAL_EGL_GL_COLORSPACE_KHR 0x309D +#define LOCAL_EGL_GL_COLORSPACE_LINEAR_KHR 0x308A +#define LOCAL_EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define LOCAL_EGL_GL_RENDERBUFFER_KHR 0x30B9 +#define LOCAL_EGL_GL_TEXTURE_2D_KHR 0x30B1 +#define LOCAL_EGL_GL_TEXTURE_3D_KHR 0x30B2 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 +#define LOCAL_EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 +#define LOCAL_EGL_GL_TEXTURE_LEVEL_KHR 0x30BC +#define LOCAL_EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD +#define LOCAL_EGL_GREEN_SIZE 0x3023 +#define LOCAL_EGL_HEIGHT 0x3056 +#define LOCAL_EGL_HORIZONTAL_RESOLUTION 0x3090 +#define LOCAL_EGL_IMAGE_PRESERVED_KHR 0x30D2 +#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_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_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_SWAP_INTERVAL 0x303C +#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_NATIVE_BUFFER_ANDROID 0x3140 +#define LOCAL_EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define LOCAL_EGL_NATIVE_RENDERABLE 0x302D +#define LOCAL_EGL_NATIVE_VISUAL_ID 0x302E +#define LOCAL_EGL_NATIVE_VISUAL_TYPE 0x302F +#define LOCAL_EGL_NONE 0x3038 +#define LOCAL_EGL_NON_CONFORMANT_CONFIG 0x3051 +#define LOCAL_EGL_NOT_INITIALIZED 0x3001 +#define LOCAL_EGL_NO_CONTEXT ((EGLContext)0) +#define LOCAL_EGL_NO_DISPLAY ((EGLDisplay)0) +#define LOCAL_EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) +#define LOCAL_EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +#define LOCAL_EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +#define LOCAL_EGL_NO_RESET_NOTIFICATION_EXT 0x31BE +#define LOCAL_EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define LOCAL_EGL_NO_STREAM_KHR ((EGLStreamKHR)0) +#define LOCAL_EGL_NO_SURFACE ((EGLSurface)0) +#define LOCAL_EGL_NO_SYNC_KHR ((EGLSyncKHR)0) +#define LOCAL_EGL_NO_SYNC_NV ((EGLSyncNV)0) +#define LOCAL_EGL_NO_TEXTURE 0x305C +#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_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_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_PIXEL_ASPECT_RATIO 0x3092 +#define LOCAL_EGL_PIXMAP_BIT 0x0002 +#define LOCAL_EGL_PLATFORM_GBM_MESA 0x31D7 +#define LOCAL_EGL_PLATFORM_WAYLAND_EXT 0x31D8 +#define LOCAL_EGL_PLATFORM_X11_EXT 0x31D5 +#define LOCAL_EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 +#define LOCAL_EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +#define LOCAL_EGL_PRODUCER_FRAME_KHR 0x3212 +#define LOCAL_EGL_PROTECTED_CONTENT_EXT 0x32C0 +#define LOCAL_EGL_READ 0x305A +#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_RENDER_BUFFER 0x3086 +#define LOCAL_EGL_RGB_BUFFER 0x308E +#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_KHR 0x30F2 +#define LOCAL_EGL_SIGNALED_NV 0x30E8 +#define LOCAL_EGL_SINGLE_BUFFER 0x3085 +#define LOCAL_EGL_SLOW_CONFIG 0x3050 +#define LOCAL_EGL_STENCIL_SIZE 0x3026 +#define LOCAL_EGL_STREAM_BIT_KHR 0x0800 +#define LOCAL_EGL_STREAM_FIFO_LENGTH_KHR 0x31FC +#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_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_PRODUCER_KHR 0x31FF +#define LOCAL_EGL_SUCCESS 0x3000 +#define LOCAL_EGL_SURFACE_TYPE 0x3033 +#define LOCAL_EGL_SWAP_BEHAVIOR 0x3093 +#define LOCAL_EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +#define LOCAL_EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF +#define LOCAL_EGL_SYNC_CL_EVENT_KHR 0x30FE +#define LOCAL_EGL_SYNC_CONDITION_KHR 0x30F8 +#define LOCAL_EGL_SYNC_CONDITION_NV 0x30EE +#define LOCAL_EGL_SYNC_FENCE_KHR 0x30F9 +#define LOCAL_EGL_SYNC_FENCE_NV 0x30EF +#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_KHR 0x30F0 +#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 +#define LOCAL_EGL_SYNC_REUSABLE_KHR 0x30FA +#define LOCAL_EGL_SYNC_STATUS_KHR 0x30F1 +#define LOCAL_EGL_SYNC_STATUS_NV 0x30E7 +#define LOCAL_EGL_SYNC_TYPE_KHR 0x30F7 +#define LOCAL_EGL_SYNC_TYPE_NV 0x30ED +#define LOCAL_EGL_TEXTURE_2D 0x305F +#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_TIMEOUT_EXPIRED_KHR 0x30F5 +#define LOCAL_EGL_TIMEOUT_EXPIRED_NV 0x30EB +#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_TRUE 1 +#define LOCAL_EGL_UNKNOWN ((EGLint)-1) +#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_WIDTH 0x3057 +#define LOCAL_EGL_WINDOW_BIT 0x0004 +#define LOCAL_EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#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_FULL_RANGE_EXT 0x3282 +#define LOCAL_EGL_YUV_NARROW_RANGE_EXT 0x3283 + + +// 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_PROFILE_MASK_ARB 0x9126 +#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_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_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_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_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_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_PROFILE_MASK_ARB 0x9126 +#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_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_ diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp new file mode 100644 index 0000000000..23090ef989 --- /dev/null +++ b/gfx/gl/GLContext.cpp @@ -0,0 +1,3150 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 <vector> +#ifdef MOZ_WIDGET_ANDROID +#include <sys/mman.h> +#endif + +#include "GLBlitHelper.h" +#include "GLReadTexImageHelper.h" +#include "GLScreenBuffer.h" + +#include "gfxCrashReporterUtils.h" +#include "gfxEnv.h" +#include "gfxUtils.h" +#include "GLContextProvider.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 "TextureGarbageBin.h" +#include "gfx2DGlue.h" +#include "gfxPrefs.h" +#include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/gfx/Logging.h" + +#include "OGLShaderProgram.h" // for ShaderProgramType + +#include "mozilla/DebugOnly.h" + +#ifdef XP_MACOSX +#include <CoreServices/CoreServices.h> +#endif + +#if defined(MOZ_WIDGET_COCOA) +#include "nsCocoaFeatures.h" +#endif + +#ifdef MOZ_WIDGET_ANDROID +#include "AndroidBridge.h" +#endif + +namespace mozilla { +namespace gl { + +using namespace mozilla::gfx; +using namespace mozilla::layers; + +#ifdef MOZ_GL_DEBUG +unsigned GLContext::sCurrentGLContextTLS = -1; +#endif + +// If adding defines, don't forget to undefine symbols. See #undef block below. +#define CORE_SYMBOL(x) { (PRFuncPtr*) &mSymbols.f##x, { #x, nullptr } } +#define CORE_EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x, #x #y, #x #z, nullptr } } +#define EXT_SYMBOL2(x,y,z) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, nullptr } } +#define EXT_SYMBOL3(x,y,z,w) { (PRFuncPtr*) &mSymbols.f##x, { #x #y, #x #z, #x #w, nullptr } } +#define END_SYMBOLS { nullptr, { nullptr } } + +// 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_texture_compression_dxt3", + "GL_ANGLE_texture_compression_dxt5", + "GL_ANGLE_timer_query", + "GL_APPLE_client_storage", + "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_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_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_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_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_draw_range_elements", + "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_multisampled_render_to_texture", + "GL_EXT_occlusion_query_boolean", + "GL_EXT_packed_depth_stencil", + "GL_EXT_read_format_bgra", + "GL_EXT_robustness", + "GL_EXT_sRGB", + "GL_EXT_sRGB_write_control", + "GL_EXT_shader_texture_lod", + "GL_EXT_texture3D", + "GL_EXT_texture_compression_dxt1", + "GL_EXT_texture_compression_s3tc", + "GL_EXT_texture_filter_anisotropic", + "GL_EXT_texture_format_BGRA8888", + "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_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_element_index_uint", + "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" +}; + +static bool +ParseGLSLVersion(GLContext* gl, uint32_t* out_version) +{ + if (gl->fGetError() != LOCAL_GL_NO_ERROR) { + MOZ_ASSERT(false, "An OpenGL error has been triggered before."); + return false; + } + + /** + * OpenGL 2.x, 3.x, 4.x specifications: + * The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows: + * + * <version number><space><vendor-specific information> + * + * The version number is either of the form major_number.minor_number or + * major_number.minor_number.release_number, where the numbers all have + * one or more digits. + * + * SHADING_LANGUAGE_VERSION is *almost* identical to VERSION. The + * difference is that the minor version always has two digits and the + * prefix has an additional 'GLSL ES' + * + * + * OpenGL ES 2.0, 3.0 specifications: + * The VERSION string is laid out as follows: + * + * "OpenGL ES N.M vendor-specific information" + * + * The version number is either of the form major_number.minor_number or + * major_number.minor_number.release_number, where the numbers all have + * one or more digits. + * + * + * Note: + * We don't care about release_number. + */ + const char* versionString = (const char*) gl->fGetString(LOCAL_GL_SHADING_LANGUAGE_VERSION); + + if (gl->fGetError() != LOCAL_GL_NO_ERROR) { + MOZ_ASSERT(false, "glGetString(GL_SHADING_LANGUAGE_VERSION) has generated an error"); + return false; + } + + if (!versionString) { + // This happens on the Android emulators. We'll just return 100 + *out_version = 100; + return true; + } + + const auto fnSkipPrefix = [&versionString](const char* prefix) { + const auto len = strlen(prefix); + if (strncmp(versionString, prefix, len) == 0) + versionString += len; + }; + + const char kGLESVersionPrefix[] = "OpenGL ES GLSL ES"; + fnSkipPrefix(kGLESVersionPrefix); + + if (gl->WorkAroundDriverBugs()) { + // Nexus 7 2013 (bug 1234441) + const char kBadGLESVersionPrefix[] = "OpenGL ES GLSL"; + fnSkipPrefix(kBadGLESVersionPrefix); + } + + const char* itr = versionString; + char* end = nullptr; + auto majorVersion = strtol(itr, &end, 10); + + if (!end) { + MOZ_ASSERT(false, "Failed to parse the GL major version number."); + return false; + } + + if (*end != '.') { + MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator."); + return false; + } + + // we skip the '.' between the major and the minor version + itr = end + 1; + end = nullptr; + + auto minorVersion = strtol(itr, &end, 10); + if (!end) { + MOZ_ASSERT(false, "Failed to parse GL's minor version number."); + return false; + } + + if (majorVersion <= 0 || majorVersion >= 100) { + MOZ_ASSERT(false, "Invalid major version."); + return false; + } + + if (minorVersion < 0 || minorVersion >= 100) { + MOZ_ASSERT(false, "Invalid minor version."); + return false; + } + + *out_version = (uint32_t) majorVersion * 100 + (uint32_t) minorVersion; + return true; +} + +static bool +ParseGLVersion(GLContext* gl, uint32_t* out_version) +{ + if (gl->fGetError() != LOCAL_GL_NO_ERROR) { + MOZ_ASSERT(false, "An OpenGL error has been triggered before."); + return false; + } + + /** + * B2G emulator bug work around: The emulator implements OpenGL ES 2.0 on + * OpenGL 3.2. The bug is that GetIntegerv(LOCAL_GL_{MAJOR,MINOR}_VERSION) + * returns OpenGL 3.2 instead of generating an error. + */ + if (!gl->IsGLES()) { + /** + * OpenGL 3.1 and OpenGL ES 3.0 both introduce GL_{MAJOR,MINOR}_VERSION + * with GetIntegerv. So we first try those constants even though we + * might not have an OpenGL context supporting them, as this is a + * better way than parsing GL_VERSION. + */ + GLint majorVersion = 0; + GLint minorVersion = 0; + + const bool ok = (gl->GetPotentialInteger(LOCAL_GL_MAJOR_VERSION, + &majorVersion) && + gl->GetPotentialInteger(LOCAL_GL_MINOR_VERSION, + &minorVersion)); + + // If it's not an OpenGL (ES) 3.0 context, we will have an error + if (ok && + majorVersion > 0 && + minorVersion >= 0) + { + *out_version = majorVersion * 100 + minorVersion * 10; + return true; + } + } + + /** + * We were not able to use GL_{MAJOR,MINOR}_VERSION, so we parse + * GL_VERSION. + * + * + * OpenGL 2.x, 3.x, 4.x specifications: + * The VERSION and SHADING_LANGUAGE_VERSION strings are laid out as follows: + * + * <version number><space><vendor-specific information> + * + * The version number is either of the form major_number.minor_number or + * major_number.minor_number.release_number, where the numbers all have + * one or more digits. + * + * + * OpenGL ES 2.0, 3.0 specifications: + * The VERSION string is laid out as follows: + * + * "OpenGL ES N.M vendor-specific information" + * + * The version number is either of the form major_number.minor_number or + * major_number.minor_number.release_number, where the numbers all have + * one or more digits. + * + * + * Note: + * We don't care about release_number. + */ + const char* versionString = (const char*)gl->fGetString(LOCAL_GL_VERSION); + + if (gl->fGetError() != LOCAL_GL_NO_ERROR) { + MOZ_ASSERT(false, "glGetString(GL_VERSION) has generated an error"); + return false; + } else if (!versionString) { + MOZ_ASSERT(false, "glGetString(GL_VERSION) has returned 0"); + return false; + } + + const char kGLESVersionPrefix[] = "OpenGL ES "; + if (strncmp(versionString, kGLESVersionPrefix, strlen(kGLESVersionPrefix)) == 0) { + versionString += strlen(kGLESVersionPrefix); + } + + const char* itr = versionString; + char* end = nullptr; + auto majorVersion = strtol(itr, &end, 10); + + if (!end) { + MOZ_ASSERT(false, "Failed to parse the GL major version number."); + return false; + } else if (*end != '.') { + MOZ_ASSERT(false, "Failed to parse GL's major-minor version number separator."); + return false; + } + + // we skip the '.' between the major and the minor version + itr = end + 1; + + end = nullptr; + + auto minorVersion = strtol(itr, &end, 10); + if (!end) { + MOZ_ASSERT(false, "Failed to parse GL's minor version number."); + return false; + } + + if (majorVersion <= 0 || majorVersion >= 100) { + MOZ_ASSERT(false, "Invalid major version."); + return false; + } else if (minorVersion < 0 || minorVersion >= 10) { + MOZ_ASSERT(false, "Invalid minor version."); + return false; + } + + *out_version = (uint32_t)majorVersion * 100 + (uint32_t)minorVersion * 10; + return true; +} + +static uint8_t +ChooseDebugFlags(CreateContextFlags createFlags) +{ + uint8_t debugFlags = 0; + +#ifdef MOZ_GL_DEBUG + if (gfxEnv::GlDebug()) { + 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::GlDebugVerbose()) { + 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 fnStringsMatch = [](const char* a, const char* b) { + return strcmp(a, b) == 0; + }; + + const char* envAbortOnError = PR_GetEnv("MOZ_GL_DEBUG_ABORT_ON_ERROR"); + if (envAbortOnError && fnStringsMatch(envAbortOnError, "0")) { + abortOnError = false; + } + } + + if (abortOnError) { + debugFlags |= GLContext::DebugFlagAbortOnError; + } +#endif + + return debugFlags; +} + +GLContext::GLContext(CreateContextFlags flags, const SurfaceCaps& caps, + GLContext* sharedContext, bool isOffscreen) + : mIsOffscreen(isOffscreen), + mContextLost(false), + mVersion(0), + mProfile(ContextProfile::Unknown), + mShadingLanguageVersion(0), + mVendor(GLVendor::Other), + mRenderer(GLRenderer::Other), + mTopError(LOCAL_GL_NO_ERROR), + mDebugFlags(ChooseDebugFlags(flags)), + mSharedContext(sharedContext), + mCaps(caps), + mScreen(nullptr), + mLockedSurface(nullptr), + mMaxTextureSize(0), + mMaxCubeMapTextureSize(0), + mMaxTextureImageSize(0), + mMaxRenderbufferSize(0), + mMaxSamples(0), + mNeedsTextureSizeChecks(false), + mNeedsFlushBeforeDeleteFB(false), + mTextureAllocCrashesOnMapFailure(false), + mNeedsCheckAfterAttachTextureToFb(false), + mWorkAroundDriverBugs(true), + mHeavyGLCallsSinceLastFlush(false) +{ + mMaxViewportDims[0] = 0; + mMaxViewportDims[1] = 0; + mOwningThreadId = PlatformThread::CurrentId(); +} + +GLContext::~GLContext() { + NS_ASSERTION(IsDestroyed(), "GLContext implementation must call MarkDestroyed in destructor!"); +#ifdef MOZ_GL_DEBUG + if (mSharedContext) { + GLContext* tip = mSharedContext; + while (tip->mSharedContext) + tip = tip->mSharedContext; + tip->SharedContextDestroyed(this); + tip->ReportOutstandingNames(); + } else { + ReportOutstandingNames(); + } +#endif +} + +/*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); +} + +static void +ClearSymbols(const GLLibraryLoader::SymLoadStruct* symbols) +{ + while (symbols->symPointer) { + *symbols->symPointer = nullptr; + symbols++; + } +} + +bool +GLContext::InitWithPrefix(const char* prefix, bool trygl) +{ + MOZ_RELEASE_ASSERT(!mSymbols.fBindFramebuffer, + "GFX: InitWithPrefix should only be called once."); + + ScopedGfxFeatureReporter reporter("GL Context"); + + if (!InitWithPrefixImpl(prefix, trygl)) { + // If initialization fails, zero the symbols to avoid hard-to-understand bugs. + mSymbols.Zero(); + NS_WARNING("GLContext::InitWithPrefix failed!"); + return false; + } + + reporter.SetSuccessful(); + return true; +} + +static bool +LoadGLSymbols(GLContext* gl, const char* prefix, bool trygl, + const GLLibraryLoader::SymLoadStruct* list, const char* desc) +{ + if (gl->LoadSymbols(list, trygl, prefix)) + 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 char* prefix, bool trygl, const SymLoadStruct* list, + GLExtensions ext) +{ + const char* extName = sExtensionNames[size_t(ext)]; + if (!LoadGLSymbols(this, prefix, trygl, list, extName)) { + MarkExtensionUnsupported(ext); + return false; + } + return true; +}; + +bool +GLContext::LoadFeatureSymbols(const char* prefix, bool trygl, const SymLoadStruct* list, + GLFeature feature) +{ + const char* featureName = GetFeatureName(feature); + if (!LoadGLSymbols(this, prefix, trygl, list, featureName)) { + MarkUnsupported(feature); + return false; + } + return true; +}; + +bool +GLContext::InitWithPrefixImpl(const char* prefix, bool trygl) +{ + mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs(); + + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fActiveTexture, { "ActiveTexture", "ActiveTextureARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fAttachShader, { "AttachShader", "AttachShaderARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindAttribLocation, { "BindAttribLocation", "BindAttribLocationARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindBuffer, { "BindBuffer", "BindBufferARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindTexture, { "BindTexture", "BindTextureARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBlendColor, { "BlendColor", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBlendEquation, { "BlendEquation", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBlendEquationSeparate, { "BlendEquationSeparate", "BlendEquationSeparateEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBlendFunc, { "BlendFunc", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBlendFuncSeparate, { "BlendFuncSeparate", "BlendFuncSeparateEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBufferData, { "BufferData", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBufferSubData, { "BufferSubData", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClear, { "Clear", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearColor, { "ClearColor", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearStencil, { "ClearStencil", nullptr } }, + { (PRFuncPtr*) &mSymbols.fColorMask, { "ColorMask", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCompressedTexImage2D, {"CompressedTexImage2D", nullptr} }, + { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage2D, {"CompressedTexSubImage2D", nullptr} }, + { (PRFuncPtr*) &mSymbols.fCullFace, { "CullFace", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDetachShader, { "DetachShader", "DetachShaderARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDepthFunc, { "DepthFunc", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDepthMask, { "DepthMask", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDisable, { "Disable", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDisableVertexAttribArray, { "DisableVertexAttribArray", "DisableVertexAttribArrayARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDrawArrays, { "DrawArrays", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDrawElements, { "DrawElements", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEnable, { "Enable", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEnableVertexAttribArray, { "EnableVertexAttribArray", "EnableVertexAttribArrayARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fFinish, { "Finish", nullptr } }, + { (PRFuncPtr*) &mSymbols.fFlush, { "Flush", nullptr } }, + { (PRFuncPtr*) &mSymbols.fFrontFace, { "FrontFace", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetActiveAttrib, { "GetActiveAttrib", "GetActiveAttribARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetActiveUniform, { "GetActiveUniform", "GetActiveUniformARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetAttachedShaders, { "GetAttachedShaders", "GetAttachedShadersARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetAttribLocation, { "GetAttribLocation", "GetAttribLocationARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetIntegerv, { "GetIntegerv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetFloatv, { "GetFloatv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetBooleanv, { "GetBooleanv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetBufferParameteriv, { "GetBufferParameteriv", "GetBufferParameterivARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetError, { "GetError", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetProgramiv, { "GetProgramiv", "GetProgramivARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetProgramInfoLog, { "GetProgramInfoLog", "GetProgramInfoLogARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexParameteri, { "TexParameteri", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexParameteriv, { "TexParameteriv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexParameterf, { "TexParameterf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetString, { "GetString", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetTexParameterfv, { "GetTexParameterfv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetTexParameteriv, { "GetTexParameteriv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformfv, { "GetUniformfv", "GetUniformfvARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformiv, { "GetUniformiv", "GetUniformivARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformLocation, { "GetUniformLocation", "GetUniformLocationARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetVertexAttribfv, { "GetVertexAttribfv", "GetVertexAttribfvARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetVertexAttribiv, { "GetVertexAttribiv", "GetVertexAttribivARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetVertexAttribPointerv, { "GetVertexAttribPointerv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fHint, { "Hint", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsBuffer, { "IsBuffer", "IsBufferARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsEnabled, { "IsEnabled", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsProgram, { "IsProgram", "IsProgramARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsShader, { "IsShader", "IsShaderARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsTexture, { "IsTexture", "IsTextureARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLineWidth, { "LineWidth", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLinkProgram, { "LinkProgram", "LinkProgramARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPixelStorei, { "PixelStorei", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPolygonOffset, { "PolygonOffset", nullptr } }, + { (PRFuncPtr*) &mSymbols.fReadPixels, { "ReadPixels", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSampleCoverage, { "SampleCoverage", nullptr } }, + { (PRFuncPtr*) &mSymbols.fScissor, { "Scissor", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilFunc, { "StencilFunc", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilFuncSeparate, { "StencilFuncSeparate", "StencilFuncSeparateEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilMask, { "StencilMask", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilMaskSeparate, { "StencilMaskSeparate", "StencilMaskSeparateEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilOp, { "StencilOp", nullptr } }, + { (PRFuncPtr*) &mSymbols.fStencilOpSeparate, { "StencilOpSeparate", "StencilOpSeparateEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexImage2D, { "TexImage2D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexSubImage2D, { "TexSubImage2D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1f, { "Uniform1f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1fv, { "Uniform1fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1i, { "Uniform1i", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1iv, { "Uniform1iv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2f, { "Uniform2f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2fv, { "Uniform2fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2i, { "Uniform2i", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2iv, { "Uniform2iv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3f, { "Uniform3f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3fv, { "Uniform3fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3i, { "Uniform3i", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3iv, { "Uniform3iv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4f, { "Uniform4f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4fv, { "Uniform4fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4i, { "Uniform4i", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4iv, { "Uniform4iv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix2fv, { "UniformMatrix2fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix3fv, { "UniformMatrix3fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix4fv, { "UniformMatrix4fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUseProgram, { "UseProgram", nullptr } }, + { (PRFuncPtr*) &mSymbols.fValidateProgram, { "ValidateProgram", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib1f, { "VertexAttrib1f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib2f, { "VertexAttrib2f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib3f, { "VertexAttrib3f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib4f, { "VertexAttrib4f", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib1fv, { "VertexAttrib1fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib2fv, { "VertexAttrib2fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib3fv, { "VertexAttrib3fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttrib4fv, { "VertexAttrib4fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fViewport, { "Viewport", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCompileShader, { "CompileShader", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCopyTexImage2D, { "CopyTexImage2D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCopyTexSubImage2D, { "CopyTexSubImage2D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetShaderiv, { "GetShaderiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetShaderInfoLog, { "GetShaderInfoLog", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetShaderSource, { "GetShaderSource", nullptr } }, + { (PRFuncPtr*) &mSymbols.fShaderSource, { "ShaderSource", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribPointer, { "VertexAttribPointer", nullptr } }, + + { (PRFuncPtr*) &mSymbols.fGenBuffers, { "GenBuffers", "GenBuffersARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenTextures, { "GenTextures", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCreateProgram, { "CreateProgram", "CreateProgramARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCreateShader, { "CreateShader", "CreateShaderARB", nullptr } }, + + { (PRFuncPtr*) &mSymbols.fDeleteBuffers, { "DeleteBuffers", "DeleteBuffersARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteTextures, { "DeleteTextures", "DeleteTexturesARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteProgram, { "DeleteProgram", "DeleteProgramARB", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteShader, { "DeleteShader", "DeleteShaderARB", nullptr } }, + + END_SYMBOLS + }; + + if (!LoadGLSymbols(this, prefix, trygl, coreSymbols, "GL")) + return false; + + //////////////// + + MakeCurrent(); + MOZ_ASSERT(mProfile != ContextProfile::Unknown); + + uint32_t version = 0; + ParseGLVersion(this, &version); + + mShadingLanguageVersion = 100; + ParseGLSLVersion(this, &mShadingLanguageVersion); + + if (ShouldSpew()) { + printf_stderr("OpenGL version detected: %u\n", version); + printf_stderr("OpenGL shading language 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)); + } + + if (version >= mVersion) { + mVersion = version; + } + // Don't fail if version < mVersion, see bug 999445, + // Mac OSX 10.6/10.7 machines with Intel GPUs claim only OpenGL 1.4 but + // have all the GL2+ extensions that we need. + + //////////////// + + // Load OpenGL ES 2.0 symbols, or desktop if we aren't using ES 2. + if (IsGLES()) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetShaderPrecisionFormat, { "GetShaderPrecisionFormat", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearDepthf, { "ClearDepthf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDepthRangef, { "DepthRangef", nullptr } }, + END_SYMBOLS + }; + + if (!LoadGLSymbols(this, prefix, trygl, symbols, "OpenGL ES")) + return false; + } else { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fClearDepth, { "ClearDepth", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDepthRange, { "DepthRange", nullptr } }, + { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fMapBuffer, { "MapBuffer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPointParameterf, { "PointParameterf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDrawBuffer, { "DrawBuffer", nullptr } }, + // The following functions are only used by Skia/GL in desktop mode. + // Other parts of Gecko should avoid using these + { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClientActiveTexture, { "ClientActiveTexture", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDisableClientState, { "DisableClientState", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEnableClientState, { "EnableClientState", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLoadIdentity, { "LoadIdentity", nullptr } }, + { (PRFuncPtr*) &mSymbols.fLoadMatrixf, { "LoadMatrixf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fMatrixMode, { "MatrixMode", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGeni, { "TexGeni", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGenf, { "TexGenf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexGenfv, { "TexGenfv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexPointer, { "VertexPointer", nullptr } }, + END_SYMBOLS + }; + + if (!LoadGLSymbols(this, prefix, trygl, 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", + "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", + "Unknown" + }; + + mRenderer = GLRenderer::Other; + for (size_t i = 0; i < size_t(GLRenderer::Other); ++i) { + if (DoesStringMatch(glRendererString, rendererMatchStrings[i])) { + mRenderer = GLRenderer(i); + break; + } + } + + if (ShouldSpew()) { + 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)]); + } + + //////////////// + + // We need this for retrieving the list of extensions on Core profiles. + if (IsFeatureProvidedByCoreSymbols(GLFeature::get_string_indexed)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetStringi, { "GetStringi", nullptr } }, + END_SYMBOLS + }; + + if (!LoadGLSymbols(this, prefix, trygl, symbols, "get_string_indexed")) { + MOZ_RELEASE_ASSERT(false, "GFX: get_string_indexed is required!"); + return false; + } + } + + InitExtensions(); + InitFeatures(); + + // Disable extensions with partial or incorrect support. + if (WorkAroundDriverBugs()) { + if (Renderer() == GLRenderer::AdrenoTM320) { + MarkUnsupported(GLFeature::standard_derivatives); + } + + 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); + } + +#ifdef XP_MACOSX + // The Mac Nvidia driver, for versions up to and including 10.8, + // don't seem to properly support this. See 814839 + // this has been fixed in Mac OS X 10.9. See 907946 + // and it also works in 10.8.3 and higher. See 1094338. + if (Vendor() == gl::GLVendor::NVIDIA && + !nsCocoaFeatures::IsAtLeastVersion(10,8,3)) + { + MarkUnsupported(GLFeature::depth_texture); + } +#endif + } + + 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 = [this, prefix, trygl](const SymLoadStruct* list, + GLFeature feature) + { + return this->LoadFeatureSymbols(prefix, trygl, 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 (!LoadGLSymbols(this, prefix, trygl, 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."); + + //////////////// + + LoadMoreSymbols(prefix, trygl); + + //////////////////////////////////////////////////////////////////////////// + + 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); + +#ifdef XP_MACOSX + if (mWorkAroundDriverBugs) { + if (mVendor == GLVendor::Intel) { + // see bug 737182 for 2D textures, bug 684882 for cube map textures. + mMaxTextureSize = std::min(mMaxTextureSize, 4096); + mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 512); + // for good measure, we align renderbuffers on what we do for 2D textures + mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 4096); + mNeedsTextureSizeChecks = true; + } else if (mVendor == GLVendor::NVIDIA) { + // See bug 879656. 8192 fails, 8191 works. + mMaxTextureSize = std::min(mMaxTextureSize, 8191); + mMaxRenderbufferSize = std::min(mMaxRenderbufferSize, 8191); + + // Part of the bug 879656, but it also doesn't hurt the 877949 + mNeedsTextureSizeChecks = true; + } + } +#endif +#ifdef MOZ_X11 + if (mWorkAroundDriverBugs) { + if (mVendor == GLVendor::Nouveau) { + // see bug 814716. Clamp MaxCubeMapTextureSize at 2K for Nouveau. + mMaxCubeMapTextureSize = std::min(mMaxCubeMapTextureSize, 2048); + mNeedsTextureSizeChecks = true; + } else if (mVendor == GLVendor::Intel) { + // Bug 1199923. Driver seems to report a larger max size than + // actually supported. + mMaxTextureSize /= 2; + mMaxRenderbufferSize /= 2; + mNeedsTextureSizeChecks = true; + } + } +#endif + if (mWorkAroundDriverBugs && + Renderer() == GLRenderer::AdrenoTM420) { + // see bug 1194923. Calling glFlush before glDeleteFramebuffers + // prevents occasional driver crash. + mNeedsFlushBeforeDeleteFB = true; + } +#ifdef MOZ_WIDGET_ANDROID + if (mWorkAroundDriverBugs && + (Renderer() == GLRenderer::AdrenoTM305 || + Renderer() == GLRenderer::AdrenoTM320 || + Renderer() == GLRenderer::AdrenoTM330) && + AndroidBridge::Bridge()->GetAPIVersion() < 21) { + // Bug 1164027. Driver crashes when functions such as + // glTexImage2D fail due to virtual memory exhaustion. + mTextureAllocCrashesOnMapFailure = true; + } +#endif +#if MOZ_WIDGET_ANDROID + if (mWorkAroundDriverBugs && + Renderer() == GLRenderer::SGX540 && + AndroidBridge::Bridge()->GetAPIVersion() <= 15) { + // Bug 1288446. Driver sometimes crashes when uploading data to a + // texture if the render target has changed since the texture was + // rendered from. Calling glCheckFramebufferStatus after + // glFramebufferTexture2D prevents the crash. + mNeedsCheckAfterAttachTextureToFb = true; + } +#endif + + mMaxTextureImageSize = mMaxTextureSize; + + if (IsSupported(GLFeature::framebuffer_multisample)) { + fGetIntegerv(LOCAL_GL_MAX_SAMPLES, (GLint*)&mMaxSamples); + } + + //////////////////////////////////////////////////////////////////////////// + + // We're ready for final setup. + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); + + // TODO: Remove SurfaceCaps::any. + if (mCaps.any) { + mCaps.any = false; + mCaps.color = true; + mCaps.alpha = false; + } + + mTexGarbageBin = new TextureGarbageBin(this); + + MOZ_ASSERT(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); + } + + mVersionString = nsPrintfCString("%u.%u.%u", mVersion / 100, (mVersion / 10) % 10, + mVersion % 10); + return true; +} + +void +GLContext::LoadMoreSymbols(const char* prefix, bool trygl) +{ + const auto fnLoadForExt = [this, prefix, trygl](const SymLoadStruct* list, + GLExtensions ext) + { + return this->LoadExtSymbols(prefix, trygl, list, ext); + }; + + const auto fnLoadForFeature = [this, prefix, trygl](const SymLoadStruct* list, + GLFeature feature) + { + return this->LoadFeatureSymbols(prefix, trygl, list, feature); + }; + + const auto fnLoadFeatureByCore = [this, fnLoadForFeature](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)) { + bool hasRobustness = false; + + if (!hasRobustness && IsExtensionSupported(ARB_robustness)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", nullptr } }, + END_SYMBOLS + }; + if (fnLoadForExt(symbols, ARB_robustness)) { + hasRobustness = true; + } + } + + if (!hasRobustness && IsExtensionSupported(EXT_robustness)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", nullptr } }, + END_SYMBOLS + }; + if (fnLoadForExt(symbols, EXT_robustness)) { + hasRobustness = true; + } + } + + if (!hasRobustness) { + MarkUnsupported(GLFeature::robustness); + } + } + + if (IsSupported(GLFeature::sync)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fFenceSync, { "FenceSync", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsSync, { "IsSync", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteSync, { "DeleteSync", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "ClientWaitSync", nullptr } }, + { (PRFuncPtr*) &mSymbols.fWaitSync, { "WaitSync", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetInteger64v, { "GetInteger64v", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetSynciv, { "GetSynciv", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::sync); + } + + if (IsExtensionSupported(OES_EGL_image)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fEGLImageTargetTexture2D, { "EGLImageTargetTexture2DOES", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEGLImageTargetRenderbufferStorage, { "EGLImageTargetRenderbufferStorageOES", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, OES_EGL_image); + } + + if (IsExtensionSupported(APPLE_texture_range)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fTextureRangeAPPLE, { "TextureRangeAPPLE", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, APPLE_texture_range); + } + + if (IsSupported(GLFeature::vertex_array_object)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArray", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArrays", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArray", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArrays", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fIsVertexArray, { "IsVertexArrayARB", "IsVertexArrayOES", "IsVertexArrayAPPLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenVertexArrays, { "GenVertexArraysARB", "GenVertexArraysOES", "GenVertexArraysAPPLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindVertexArray, { "BindVertexArrayARB", "BindVertexArrayOES", "BindVertexArrayAPPLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteVertexArrays, { "DeleteVertexArraysARB", "DeleteVertexArraysOES", "DeleteVertexArraysAPPLE", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::vertex_array_object); + } + + if (IsSupported(GLFeature::draw_instanced)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstanced", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstanced", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawArraysInstanced, { "DrawArraysInstancedARB", "DrawArraysInstancedEXT", "DrawArraysInstancedNV", "DrawArraysInstancedANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDrawElementsInstanced, { "DrawElementsInstancedARB", "DrawElementsInstancedEXT", "DrawElementsInstancedNV", "DrawElementsInstancedANGLE", nullptr } + }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_instanced); + } + + if (IsSupported(GLFeature::instanced_arrays)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisor", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fVertexAttribDivisor, { "VertexAttribDivisorARB", "VertexAttribDivisorNV", "VertexAttribDivisorANGLE", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::instanced_arrays); + } + + if (IsSupported(GLFeature::texture_storage)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3D", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fTexStorage2D, { "TexStorage2DEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexStorage3D, { "TexStorage3DEXT", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage); + } + + if (IsSupported(GLFeature::sampler_objects)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGenSamplers, { "GenSamplers", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteSamplers, { "DeleteSamplers", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsSampler, { "IsSampler", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindSampler, { "BindSampler", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSamplerParameteri, { "SamplerParameteri", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSamplerParameteriv, { "SamplerParameteriv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSamplerParameterf, { "SamplerParameterf", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSamplerParameterfv, { "SamplerParameterfv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetSamplerParameteriv, { "GetSamplerParameteriv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetSamplerParameterfv, { "GetSamplerParameterfv", nullptr } }, + 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, { "BindBufferBase", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRange", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacks", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedback", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacks", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedback", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedback", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedback", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryings", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVarying", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedback", nullptr } }, + { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedback", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBindBufferBase, { "BindBufferBaseEXT", "BindBufferBaseNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindBufferRange, { "BindBufferRangeEXT", "BindBufferRangeNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenTransformFeedbacks, { "GenTransformFeedbacksNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBindTransformFeedback, { "BindTransformFeedbackNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteTransformFeedbacks, { "DeleteTransformFeedbacksNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsTransformFeedback, { "IsTransformFeedbackNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fBeginTransformFeedback, { "BeginTransformFeedbackEXT", "BeginTransformFeedbackNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEndTransformFeedback, { "EndTransformFeedbackEXT", "EndTransformFeedbackNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTransformFeedbackVaryings, { "TransformFeedbackVaryingsEXT", "TransformFeedbackVaryingsNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetTransformFeedbackVarying, { "GetTransformFeedbackVaryingEXT", "GetTransformFeedbackVaryingNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPauseTransformFeedback, { "PauseTransformFeedbackNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fResumeTransformFeedback, { "ResumeTransformFeedbackNV", nullptr } }, + END_SYMBOLS + }; + if (!fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_storage)) { + // Also mark bind_buffer_offset as unsupported. + MarkUnsupported(GLFeature::bind_buffer_offset); + } + } + + if (IsSupported(GLFeature::bind_buffer_offset)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBindBufferOffset, { "BindBufferOffset", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBindBufferOffset, + { "BindBufferOffsetEXT", "BindBufferOffsetNV", nullptr } + }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::bind_buffer_offset); + } + + if (IsSupported(GLFeature::query_counter)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounter", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQueryCounter, { "QueryCounterEXT", "QueryCounterANGLE", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::query_counter); + } + + if (IsSupported(GLFeature::query_objects)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQuery", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueries", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueries", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQuery", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQuery", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fBeginQuery, { "BeginQueryEXT", "BeginQueryANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGenQueries, { "GenQueriesEXT", "GenQueriesANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteQueries, { "DeleteQueriesEXT", "DeleteQueriesANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fEndQuery, { "EndQueryEXT", "EndQueryANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryiv, { "GetQueryivEXT", "GetQueryivANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectuiv, { "GetQueryObjectuivEXT", "GetQueryObjectuivANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsQuery, { "IsQueryEXT", "IsQueryANGLE", nullptr } }, + 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, { "GetQueryObjecti64v", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64v", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetQueryObjecti64v, { "GetQueryObjecti64vEXT", "GetQueryObjecti64vANGLE", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetQueryObjectui64v, { "GetQueryObjectui64vEXT", "GetQueryObjectui64vANGLE", nullptr } }, + 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, { "GetQueryObjectiv", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetQueryObjectiv, { "GetQueryObjectivEXT", "GetQueryObjectivANGLE", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_query_object_iv); + } + + if (IsSupported(GLFeature::clear_buffers)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fClearBufferfi, { "ClearBufferfi", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearBufferfv, { "ClearBufferfv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearBufferiv, { "ClearBufferiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClearBufferuiv, { "ClearBufferuiv", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::clear_buffers); + } + + if (IsSupported(GLFeature::copy_buffer)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fCopyBufferSubData, { "CopyBufferSubData", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::copy_buffer); + } + + if (IsSupported(GLFeature::draw_buffers)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffers", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawBuffers, { "DrawBuffersARB", "DrawBuffersEXT", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_buffers); + } + + if (IsSupported(GLFeature::draw_range_elements)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElements", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::draw_range_elements); + } + + if (IsSupported(GLFeature::get_integer_indexed)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegeri_v", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] ={ + { (PRFuncPtr*) &mSymbols.fGetIntegeri_v, { "GetIntegerIndexedvEXT", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::get_integer_indexed); + } + + if (IsSupported(GLFeature::get_integer64_indexed)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetInteger64i_v, { "GetInteger64i_v", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::get_integer64_indexed); + } + + if (IsSupported(GLFeature::gpu_shader4)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGetVertexAttribIiv, { "GetVertexAttribIiv", "GetVertexAttribIivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetVertexAttribIuiv, { "GetVertexAttribIuiv", "GetVertexAttribIuivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribI4i, { "VertexAttribI4i", "VertexAttribI4iEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribI4iv, { "VertexAttribI4iv","VertexAttribI4ivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribI4ui, { "VertexAttribI4ui", "VertexAttribI4uiEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribI4uiv, { "VertexAttribI4uiv", "VertexAttribI4uivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fVertexAttribIPointer, { "VertexAttribIPointer", "VertexAttribIPointerEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1ui, { "Uniform1ui", "Uniform1uiEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2ui, { "Uniform2ui", "Uniform2uiEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3ui, { "Uniform3ui", "Uniform3uiEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4ui, { "Uniform4ui", "Uniform4uiEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform1uiv, { "Uniform1uiv", "Uniform1uivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform2uiv, { "Uniform2uiv", "Uniform2uivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform3uiv, { "Uniform3uiv", "Uniform3uivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniform4uiv, { "Uniform4uiv", "Uniform4uivEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetFragDataLocation, { "GetFragDataLocation", "GetFragDataLocationEXT", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformuiv, { "GetUniformuiv", "GetUniformuivEXT", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::gpu_shader4); + } + + if (IsSupported(GLFeature::map_buffer_range)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fMapBufferRange, { "MapBufferRange", nullptr } }, + { (PRFuncPtr*) &mSymbols.fFlushMappedBufferRange, { "FlushMappedBufferRange", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUnmapBuffer, { "UnmapBuffer", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::map_buffer_range); + } + + if (IsSupported(GLFeature::texture_3D)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fTexImage3D, { "TexImage3D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3DEXT", "TexSubImage3DOES", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D); + } + + if (IsSupported(GLFeature::texture_3D_compressed)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3D", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3D", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCompressedTexImage3D, { "CompressedTexImage3DARB", "CompressedTexImage3DOES", nullptr } }, + { (PRFuncPtr*) &mSymbols.fCompressedTexSubImage3D, { "CompressedTexSubImage3DARB", "CompressedTexSubImage3DOES", nullptr } }, + END_SYMBOLS + }; + fnLoadFeatureByCore(coreSymbols, extSymbols, GLFeature::texture_3D_compressed); + } + + if (IsSupported(GLFeature::texture_3D_copy)) { + const SymLoadStruct coreSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3D", nullptr } }, + END_SYMBOLS + }; + const SymLoadStruct extSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCopyTexSubImage3D, { "CopyTexSubImage3DEXT", "CopyTexSubImage3DOES", nullptr } }, + 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, { "GetUniformIndices", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetActiveUniformsiv, { "GetActiveUniformsiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetUniformBlockIndex, { "GetUniformBlockIndex", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockiv, { "GetActiveUniformBlockiv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetActiveUniformBlockName, { "GetActiveUniformBlockName", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformBlockBinding, { "UniformBlockBinding", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::uniform_buffer_object); + } + + if (IsSupported(GLFeature::uniform_matrix_nonsquare)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fUniformMatrix2x3fv, { "UniformMatrix2x3fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix2x4fv, { "UniformMatrix2x4fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix3x2fv, { "UniformMatrix3x2fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix3x4fv, { "UniformMatrix3x4fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix4x2fv, { "UniformMatrix4x2fv", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUniformMatrix4x3fv, { "UniformMatrix4x3fv", nullptr } }, + 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, { "InvalidateFramebuffer", nullptr } }, + { (PRFuncPtr*) &mSymbols.fInvalidateSubFramebuffer, { "InvalidateSubFramebuffer", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::invalidate_framebuffer); + } + + if (IsSupported(GLFeature::prim_restart)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fPrimitiveRestartIndex, { "PrimitiveRestartIndex", "PrimitiveRestartIndexNV", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::prim_restart); + } + + if (IsExtensionSupported(KHR_debug)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fDebugMessageControl, { "DebugMessageControl", "DebugMessageControlKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDebugMessageInsert, { "DebugMessageInsert", "DebugMessageInsertKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDebugMessageCallback, { "DebugMessageCallback", "DebugMessageCallbackKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetDebugMessageLog, { "GetDebugMessageLog", "GetDebugMessageLogKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetPointerv, { "GetPointerv", "GetPointervKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPushDebugGroup, { "PushDebugGroup", "PushDebugGroupKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fPopDebugGroup, { "PopDebugGroup", "PopDebugGroupKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fObjectLabel, { "ObjectLabel", "ObjectLabelKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetObjectLabel, { "GetObjectLabel", "GetObjectLabelKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fObjectPtrLabel, { "ObjectPtrLabel", "ObjectPtrLabelKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetObjectPtrLabel, { "GetObjectPtrLabel", "GetObjectPtrLabelKHR", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, KHR_debug); + } + + if (IsExtensionSupported(NV_fence)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fGenFences, { "GenFencesNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDeleteFences, { "DeleteFencesNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fSetFence, { "SetFenceNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fTestFence, { "TestFenceNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fFinishFence, { "FinishFenceNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fIsFence, { "IsFenceNV", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetFenceiv, { "GetFenceivNV", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, NV_fence); + } + + if (IsExtensionSupported(NV_texture_barrier)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fTextureBarrier, { "TextureBarrierNV", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, NV_texture_barrier); + } + + if (IsSupported(GLFeature::read_buffer)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fReadBuffer, { "ReadBuffer", nullptr } }, + END_SYMBOLS + }; + fnLoadForFeature(symbols, GLFeature::read_buffer); + } + + if (IsExtensionSupported(APPLE_framebuffer_multisample)) { + const SymLoadStruct symbols[] = { + { (PRFuncPtr*) &mSymbols.fResolveMultisampleFramebufferAPPLE, { "ResolveMultisampleFramebufferAPPLE", nullptr } }, + END_SYMBOLS + }; + fnLoadForExt(symbols, APPLE_framebuffer_multisample); + } + + // Load developer symbols, don't fail if we can't find them. + const SymLoadStruct devSymbols[] = { + { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } }, + END_SYMBOLS + }; + const bool warnOnFailures = ShouldSpew(); + LoadSymbols(devSymbols, trygl, prefix, 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 = NS_LITERAL_CSTRING("SOURCE_API"); + break; + case LOCAL_GL_DEBUG_SOURCE_WINDOW_SYSTEM: + sourceStr = NS_LITERAL_CSTRING("SOURCE_WINDOW_SYSTEM"); + break; + case LOCAL_GL_DEBUG_SOURCE_SHADER_COMPILER: + sourceStr = NS_LITERAL_CSTRING("SOURCE_SHADER_COMPILER"); + break; + case LOCAL_GL_DEBUG_SOURCE_THIRD_PARTY: + sourceStr = NS_LITERAL_CSTRING("SOURCE_THIRD_PARTY"); + break; + case LOCAL_GL_DEBUG_SOURCE_APPLICATION: + sourceStr = NS_LITERAL_CSTRING("SOURCE_APPLICATION"); + break; + case LOCAL_GL_DEBUG_SOURCE_OTHER: + sourceStr = NS_LITERAL_CSTRING("SOURCE_OTHER"); + break; + default: + sourceStr = nsPrintfCString("<source 0x%04x>", source); + break; + } + + nsAutoCString typeStr; + switch (type) { + case LOCAL_GL_DEBUG_TYPE_ERROR: + typeStr = NS_LITERAL_CSTRING("TYPE_ERROR"); + break; + case LOCAL_GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + typeStr = NS_LITERAL_CSTRING("TYPE_DEPRECATED_BEHAVIOR"); + break; + case LOCAL_GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + typeStr = NS_LITERAL_CSTRING("TYPE_UNDEFINED_BEHAVIOR"); + break; + case LOCAL_GL_DEBUG_TYPE_PORTABILITY: + typeStr = NS_LITERAL_CSTRING("TYPE_PORTABILITY"); + break; + case LOCAL_GL_DEBUG_TYPE_PERFORMANCE: + typeStr = NS_LITERAL_CSTRING("TYPE_PERFORMANCE"); + break; + case LOCAL_GL_DEBUG_TYPE_OTHER: + typeStr = NS_LITERAL_CSTRING("TYPE_OTHER"); + break; + case LOCAL_GL_DEBUG_TYPE_MARKER: + typeStr = NS_LITERAL_CSTRING("TYPE_MARKER"); + break; + default: + typeStr = nsPrintfCString("<type 0x%04x>", type); + break; + } + + nsAutoCString sevStr; + switch (severity) { + case LOCAL_GL_DEBUG_SEVERITY_HIGH: + sevStr = NS_LITERAL_CSTRING("SEVERITY_HIGH"); + break; + case LOCAL_GL_DEBUG_SEVERITY_MEDIUM: + sevStr = NS_LITERAL_CSTRING("SEVERITY_MEDIUM"); + break; + case LOCAL_GL_DEBUG_SEVERITY_LOW: + sevStr = NS_LITERAL_CSTRING("SEVERITY_LOW"); + break; + case LOCAL_GL_DEBUG_SEVERITY_NOTIFICATION: + sevStr = NS_LITERAL_CSTRING("SEVERITY_NOTIFICATION"); + 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_ASSERT(IsCurrent()); + + std::vector<nsCString> driverExtensionList; + + if (IsFeatureProvidedByCoreSymbols(GLFeature::get_string_indexed)) { + GLuint count = 0; + GetUIntegerv(LOCAL_GL_NUM_EXTENSIONS, &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)); + } + } else { + MOZ_ALWAYS_TRUE(!fGetError()); + const char* rawExts = (const char*)fGetString(LOCAL_GL_EXTENSIONS); + MOZ_ALWAYS_TRUE(!fGetError()); + + if (rawExts) { + nsDependentCString exts(rawExts); + SplitByChar(exts, ' ', &driverExtensionList); + } + } + + 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); + } + +#ifdef MOZ_WIDGET_ANDROID + if (Vendor() == GLVendor::Imagination && + Renderer() == GLRenderer::SGX544MP && + AndroidBridge::Bridge()->GetAPIVersion() < 21) + { + // Bug 1026404 + MarkExtensionUnsupported(OES_EGL_image); + MarkExtensionUnsupported(OES_EGL_image_external); + } +#endif + + 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); + // there seems to be a similar issue for EXT_texture_format_BGRA8888 + // on the Android 4.3 emulator + MarkExtensionSupported(EXT_texture_format_BGRA8888); + } + + 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 (nsCocoaFeatures::OSXVersionMajor() == 10 && + nsCocoaFeatures::OSXVersionMinor() >= 9 && + Renderer() == GLRenderer::IntelHD3000) + { + MarkExtensionUnsupported(EXT_texture_compression_s3tc); + } +#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; +} + +GLFormats +GLContext::ChooseGLFormats(const SurfaceCaps& caps) const +{ + GLFormats formats; + + // If we're on ES2 hardware and we have an explicit request for 16 bits of color or less + // OR we don't support full 8-bit color, return a 4444 or 565 format. + bool bpp16 = caps.bpp16; + if (IsGLES()) { + if (!IsExtensionSupported(OES_rgb8_rgba8)) + bpp16 = true; + } else { + // RGB565 is uncommon on desktop, requiring ARB_ES2_compatibility. + // Since it's also vanishingly useless there, let's not support it. + bpp16 = false; + } + + if (bpp16) { + MOZ_ASSERT(IsGLES()); + if (caps.alpha) { + formats.color_texInternalFormat = LOCAL_GL_RGBA; + formats.color_texFormat = LOCAL_GL_RGBA; + formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_4_4_4_4; + formats.color_rbFormat = LOCAL_GL_RGBA4; + } else { + formats.color_texInternalFormat = LOCAL_GL_RGB; + formats.color_texFormat = LOCAL_GL_RGB; + formats.color_texType = LOCAL_GL_UNSIGNED_SHORT_5_6_5; + formats.color_rbFormat = LOCAL_GL_RGB565; + } + } else { + formats.color_texType = LOCAL_GL_UNSIGNED_BYTE; + + if (caps.alpha) { + formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGBA : LOCAL_GL_RGBA8; + formats.color_texFormat = LOCAL_GL_RGBA; + formats.color_rbFormat = LOCAL_GL_RGBA8; + } else { + formats.color_texInternalFormat = IsGLES() ? LOCAL_GL_RGB : LOCAL_GL_RGB8; + formats.color_texFormat = LOCAL_GL_RGB; + formats.color_rbFormat = LOCAL_GL_RGB8; + } + } + + uint32_t msaaLevel = gfxPrefs::MSAALevel(); + GLsizei samples = msaaLevel * msaaLevel; + samples = std::min(samples, mMaxSamples); + + // Bug 778765. + if (WorkAroundDriverBugs() && samples == 1) { + samples = 0; + } + formats.samples = samples; + + + // Be clear that these are 0 if unavailable. + formats.depthStencil = 0; + if (IsSupported(GLFeature::packed_depth_stencil)) { + formats.depthStencil = LOCAL_GL_DEPTH24_STENCIL8; + } + + formats.depth = 0; + if (IsGLES()) { + if (IsExtensionSupported(OES_depth24)) { + formats.depth = LOCAL_GL_DEPTH_COMPONENT24; + } else { + formats.depth = LOCAL_GL_DEPTH_COMPONENT16; + } + } else { + formats.depth = LOCAL_GL_DEPTH_COMPONENT24; + } + + formats.stencil = LOCAL_GL_STENCIL_INDEX8; + + return formats; +} + +bool +GLContext::IsFramebufferComplete(GLuint fb, GLenum* pStatus) +{ + MOZ_ASSERT(fb); + + ScopedBindFramebuffer autoFB(this, fb); + MOZ_ASSERT(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_ASSERT(fIsFramebuffer(fb)); // It only counts after being bound. + + if (colorTex) { + MOZ_ASSERT(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_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(colorRB)); + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_RENDERBUFFER, + colorRB); + } + + if (depthRB) { + MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(depthRB)); + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_DEPTH_ATTACHMENT, + LOCAL_GL_RENDERBUFFER, + depthRB); + } + + if (stencilRB) { + MOZ_ASSERT_IF(Renderer() != GLRenderer::AndroidEmulator, fIsRenderbuffer(stencilRB)); + 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(GetFB() == 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 + if (ShouldSpew()) { + printf_stderr("Framebuffer status: %X\n", status); + } + #endif + isComplete = false; + } + + if (!IsFramebufferComplete(readFB, &status)) { + NS_WARNING("ReadFBO: Incomplete"); + #ifdef MOZ_GL_DEBUG + if (ShouldSpew()) { + printf_stderr("Framebuffer status: %X\n", status); + } + #endif + isComplete = false; + } + + if (drawFB_out) { + *drawFB_out = drawFB; + } else if (drawFB) { + NS_RUNTIMEABORT("drawFB created when not requested!"); + } + + if (readFB_out) { + *readFB_out = readFB; + } else if (readFB) { + NS_RUNTIMEABORT("readFB created when not requested!"); + } + + return isComplete; +} + + +void +GLContext::ClearSafely() +{ + // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state, + // and in the case of the backbuffer of a WebGL context, state is exposed to scripts. + // + // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of + // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so + // WebGL keeps track of GL state to avoid having to query it everytime, and also tries to only do work for actually + // present buffers (e.g. stencil buffer). Doing that here seems like premature optimization, + // as ClearSafely() is called only when e.g. a canvas is resized, not on every animation frame. + + realGLboolean scissorTestEnabled; + realGLboolean ditherEnabled; + realGLboolean colorWriteMask[4]; + realGLboolean depthWriteMask; + GLint stencilWriteMaskFront, stencilWriteMaskBack; + GLfloat colorClearValue[4]; + GLfloat depthClearValue; + GLint stencilClearValue; + + // save current GL state + fGetBooleanv(LOCAL_GL_SCISSOR_TEST, &scissorTestEnabled); + fGetBooleanv(LOCAL_GL_DITHER, &ditherEnabled); + fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask); + fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask); + fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, &stencilWriteMaskFront); + fGetIntegerv(LOCAL_GL_STENCIL_BACK_WRITEMASK, &stencilWriteMaskBack); + fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue); + fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue); + fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &stencilClearValue); + + // prepare GL state for clearing + fDisable(LOCAL_GL_SCISSOR_TEST); + fDisable(LOCAL_GL_DITHER); + + fColorMask(1, 1, 1, 1); + fClearColor(0.f, 0.f, 0.f, 0.f); + + fDepthMask(1); + fClearDepth(1.0f); + + fStencilMask(0xffffffff); + fClearStencil(0); + + // do clear + fClear(LOCAL_GL_COLOR_BUFFER_BIT | + LOCAL_GL_DEPTH_BUFFER_BIT | + LOCAL_GL_STENCIL_BUFFER_BIT); + + // restore GL state after clearing + fColorMask(colorWriteMask[0], + colorWriteMask[1], + colorWriteMask[2], + colorWriteMask[3]); + fClearColor(colorClearValue[0], + colorClearValue[1], + colorClearValue[2], + colorClearValue[3]); + + fDepthMask(depthWriteMask); + fClearDepth(depthClearValue); + + fStencilMaskSeparate(LOCAL_GL_FRONT, stencilWriteMaskFront); + fStencilMaskSeparate(LOCAL_GL_BACK, stencilWriteMaskBack); + fClearStencil(stencilClearValue); + + if (ditherEnabled) + fEnable(LOCAL_GL_DITHER); + else + fDisable(LOCAL_GL_DITHER); + + if (scissorTestEnabled) + fEnable(LOCAL_GL_SCISSOR_TEST); + else + fDisable(LOCAL_GL_SCISSOR_TEST); + +} + +void +GLContext::MarkDestroyed() +{ + if (IsDestroyed()) + return; + + // Null these before they're naturally nulled after dtor, as we want GLContext to + // still be alive in *their* dtors. + mScreen = nullptr; + mBlitHelper = nullptr; + mReadTexImageHelper = nullptr; + + if (MakeCurrent()) { + mTexGarbageBin->GLContextTeardown(); + } else { + NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown."); + } + + mSymbols.Zero(); +} + +#ifdef MOZ_GL_DEBUG +/* 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); + 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 /* DEBUG */ + +void +GLContext::GuaranteeResolve() +{ + if (mScreen) { + mScreen->AssureBlitted(); + } + fFinish(); +} + +const gfx::IntSize& +GLContext::OffscreenSize() const +{ + MOZ_ASSERT(IsOffscreen()); + return mScreen->Size(); +} + +bool +GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps) +{ + UniquePtr<GLScreenBuffer> newScreen = GLScreenBuffer::Create(this, size, caps); + if (!newScreen) + return false; + + if (!newScreen->Resize(size)) { + return false; + } + + // This will rebind to 0 (Screen) if needed when + // it falls out of scope. + ScopedBindFramebuffer autoFB(this); + + mScreen = Move(newScreen); + + return true; +} + +bool +GLContext::ResizeScreenBuffer(const IntSize& size) +{ + if (!IsOffscreenSizeAllowed(size)) + return false; + + return mScreen->Resize(size); +} + +void +GLContext::ForceDirtyScreen() +{ + ScopedBindFramebuffer autoFB(0); + + BeforeGLDrawCall(); + // no-op; just pretend we did something + AfterGLDrawCall(); +} + +void +GLContext::CleanDirtyScreen() +{ + ScopedBindFramebuffer autoFB(0); + + BeforeGLReadCall(); + // no-op; we just want to make sure the Read FBO is updated if it needs to be + AfterGLReadCall(); +} + +void +GLContext::EmptyTexGarbageBin() +{ + TexGarbageBin()->EmptyGarbage(); +} + +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::IsOwningThreadCurrent() +{ + 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; + } + MakeCurrent(); + fFlush(); +} + +/*static*/ bool +GLContext::ShouldDumpExts() +{ + return gfxEnv::GlDumpExtensions(); +} + +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::GlSpew(); +} + +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; + continue; + } + + nsDependentCSubstring substr(str, start); + out->push_back(nsCString(substr)); +} + +void +GLContext::Readback(SharedSurface* src, gfx::DataSourceSurface* dest) +{ + MOZ_ASSERT(src && dest); + MOZ_ASSERT(dest->GetSize() == src->mSize); + MOZ_ASSERT(dest->GetFormat() == (src->mHasAlpha ? SurfaceFormat::B8G8R8A8 + : SurfaceFormat::B8G8R8X8)); + + MakeCurrent(); + + SharedSurface* prev = GetLockedSurface(); + + const bool needsSwap = src != prev; + if (needsSwap) { + if (prev) + prev->UnlockProd(); + src->LockProd(); + } + + GLuint tempFB = 0; + GLuint tempTex = 0; + + { + ScopedBindFramebuffer autoFB(this); + + // We're consuming from the producer side, so which do we use? + // Really, we just want a read-only lock, so ConsumerAcquire is the best match. + src->ProducerReadAcquire(); + + if (src->mAttachType == AttachmentType::Screen) { + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); + } else { + fGenFramebuffers(1, &tempFB); + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, tempFB); + + switch (src->mAttachType) { + case AttachmentType::GLTexture: + fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, + src->ProdTextureTarget(), src->ProdTexture(), 0); + break; + case AttachmentType::GLRenderbuffer: + fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_RENDERBUFFER, src->ProdRenderbuffer()); + break; + default: + MOZ_CRASH("GFX: bad `src->mAttachType`."); + } + + DebugOnly<GLenum> status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE); + } + + if (src->NeedsIndirectReads()) { + fGenTextures(1, &tempTex); + { + ScopedBindTexture autoTex(this, tempTex); + + GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA + : LOCAL_GL_RGB; + auto width = src->mSize.width; + auto height = src->mSize.height; + fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width, + height, 0); + } + + fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, tempTex, 0); + } + + ReadPixelsIntoDataSurface(this, dest); + + src->ProducerReadRelease(); + } + + if (tempFB) + fDeleteFramebuffers(1, &tempFB); + + if (tempTex) { + fDeleteTextures(1, &tempTex); + } + + if (needsSwap) { + src->UnlockProd(); + if (prev) + prev->LockProd(); + } +} + +// Do whatever tear-down is necessary after drawing to our offscreen FBO, +// if it's bound. +void +GLContext::AfterGLDrawCall() +{ + if (mScreen) { + mScreen->AfterDrawCall(); + } + mHeavyGLCallsSinceLastFlush = true; +} + +// Do whatever setup is necessary to read from our offscreen FBO, if it's +// bound. +void +GLContext::BeforeGLReadCall() +{ + if (mScreen) + mScreen->BeforeReadCall(); +} + +void +GLContext::fBindFramebuffer(GLenum target, GLuint framebuffer) +{ + if (!mScreen) { + raw_fBindFramebuffer(target, framebuffer); + return; + } + + switch (target) { + case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: + mScreen->BindDrawFB(framebuffer); + return; + + case LOCAL_GL_READ_FRAMEBUFFER_EXT: + mScreen->BindReadFB(framebuffer); + return; + + case LOCAL_GL_FRAMEBUFFER: + mScreen->BindFB(framebuffer); + return; + + default: + // Nothing we care about, likely an error. + break; + } + + raw_fBindFramebuffer(target, framebuffer); +} + +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(); + bool didCopyTexImage2D = false; + if (mScreen) { + didCopyTexImage2D = mScreen->CopyTexImage2D(target, level, internalformat, x, + y, width, height, border); + } + + if (!didCopyTexImage2D) { + raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height, + border); + } + AfterGLReadCall(); +} + +void +GLContext::fGetIntegerv(GLenum pname, GLint* params) +{ + switch (pname) { + // LOCAL_GL_FRAMEBUFFER_BINDING is equal to + // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, + // so we don't need two cases. + case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT: + if (mScreen) { + *params = mScreen->GetDrawFB(); + } else { + raw_fGetIntegerv(pname, params); + } + break; + + case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT: + if (mScreen) { + *params = mScreen->GetReadFB(); + } else { + raw_fGetIntegerv(pname, params); + } + break; + + case LOCAL_GL_MAX_TEXTURE_SIZE: + MOZ_ASSERT(mMaxTextureSize>0); + *params = mMaxTextureSize; + break; + + case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE: + MOZ_ASSERT(mMaxCubeMapTextureSize>0); + *params = mMaxCubeMapTextureSize; + break; + + case LOCAL_GL_MAX_RENDERBUFFER_SIZE: + MOZ_ASSERT(mMaxRenderbufferSize>0); + *params = mMaxRenderbufferSize; + break; + + case LOCAL_GL_VIEWPORT: + for (size_t i = 0; i < 4; i++) { + params[i] = mViewportRect[i]; + } + break; + + case LOCAL_GL_SCISSOR_BOX: + for (size_t i = 0; i < 4; i++) { + params[i] = mScissorRect[i]; + } + break; + + default: + raw_fGetIntegerv(pname, params); + break; + } +} + +void +GLContext::fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLvoid* pixels) +{ + BeforeGLReadCall(); + + bool didReadPixels = false; + if (mScreen) { + didReadPixels = mScreen->ReadPixels(x, y, width, height, format, type, pixels); + } + + if (!didReadPixels) { + 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) +{ + if (mScreen) { + // Notify mScreen which framebuffers we're deleting. + // Otherwise, we will get framebuffer binding mispredictions. + for (int i = 0; i < n; i++) { + mScreen->DeletingFB(names[i]); + } + } + + // 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); +} + +GLuint +GLContext::GetDrawFB() +{ + if (mScreen) + return mScreen->GetDrawFB(); + + GLuint ret = 0; + GetUIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret); + return ret; +} + +GLuint +GLContext::GetReadFB() +{ + if (mScreen) + return mScreen->GetReadFB(); + + GLenum bindEnum = IsSupported(GLFeature::split_framebuffer) + ? LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT + : LOCAL_GL_FRAMEBUFFER_BINDING; + + GLuint ret = 0; + GetUIntegerv(bindEnum, &ret); + return ret; +} + +GLuint +GLContext::GetFB() +{ + if (mScreen) { + // This has a very important extra assert that checks that we're + // not accidentally ignoring a situation where the draw and read + // FBs differ. + return mScreen->GetFB(); + } + + GLuint ret = 0; + GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret); + return ret; +} + +bool +GLContext::InitOffscreen(const gfx::IntSize& size, const SurfaceCaps& caps) +{ + if (!CreateScreenBuffer(size, caps)) + return false; + + MakeCurrent(); + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0); + fScissor(0, 0, size.width, size.height); + fViewport(0, 0, size.width, size.height); + + mCaps = mScreen->mCaps; + MOZ_ASSERT(!mCaps.any); + + return true; +} + +bool +GLContext::IsDrawingToDefaultFramebuffer() +{ + return Screen()->IsDrawFramebufferDefault(); +} + +GLuint +CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat, + GLenum aType, const gfx::IntSize& aSize, bool linear) +{ + GLuint tex = 0; + aGL->fGenTextures(1, &tex); + ScopedBindTexture autoTex(aGL, tex); + + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, + LOCAL_GL_TEXTURE_MIN_FILTER, linear ? LOCAL_GL_LINEAR + : LOCAL_GL_NEAREST); + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, + LOCAL_GL_TEXTURE_MAG_FILTER, linear ? LOCAL_GL_LINEAR + : LOCAL_GL_NEAREST); + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, + LOCAL_GL_CLAMP_TO_EDGE); + aGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, + LOCAL_GL_CLAMP_TO_EDGE); + + aGL->fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + aInternalFormat, + aSize.width, aSize.height, + 0, + aFormat, + aType, + nullptr); + + return tex; +} + +GLuint +CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats, + const gfx::IntSize& aSize) +{ + MOZ_ASSERT(aFormats.color_texInternalFormat); + MOZ_ASSERT(aFormats.color_texFormat); + MOZ_ASSERT(aFormats.color_texType); + + GLenum internalFormat = aFormats.color_texInternalFormat; + GLenum unpackFormat = aFormats.color_texFormat; + GLenum unpackType = aFormats.color_texType; + if (aGL->IsANGLE()) { + MOZ_ASSERT(internalFormat == LOCAL_GL_RGBA); + MOZ_ASSERT(unpackFormat == LOCAL_GL_RGBA); + MOZ_ASSERT(unpackType == LOCAL_GL_UNSIGNED_BYTE); + internalFormat = LOCAL_GL_BGRA_EXT; + unpackFormat = LOCAL_GL_BGRA_EXT; + } + + return CreateTexture(aGL, internalFormat, unpackFormat, unpackType, aSize); +} + +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: + return 1 * multiplier; + case LOCAL_GL_LUMINANCE_ALPHA: + 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) + { + return 2; + } + + gfxCriticalError() << "Unknown texture type " << type << " or format " << format; + return 0; +} + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h new file mode 100644 index 0000000000..f205630705 --- /dev/null +++ b/gfx/gl/GLContext.h @@ -0,0 +1,3736 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 <ctype.h> +#include <stdint.h> +#include <stdio.h> +#include <map> +#include <queue> +#include <stack> + +#ifdef DEBUG +#include <string.h> +#endif + +#ifdef GetClassName +#undef GetClassName +#endif + +// Define MOZ_GL_DEBUG unconditionally to enable GL debugging in opt +// builds. +#ifdef DEBUG +#define MOZ_GL_DEBUG 1 +#endif + +#include "../../mfbt/RefPtr.h" +#include "../../mfbt/UniquePtr.h" + +#include "GLDefs.h" +#include "GLLibraryLoader.h" +#include "nsISupportsImpl.h" +#include "plstr.h" +#include "GLContextTypes.h" +#include "SurfaceTypes.h" +#include "GLContextSymbols.h" +#include "base/platform_thread.h" // for PlatformThreadId +#include "mozilla/GenericRefCounted.h" +#include "mozilla/WeakPtr.h" +#include "gfx2DGlue.h" +#include "GeckoProfiler.h" + +class nsIWidget; + +namespace android { + class GraphicBuffer; +} // namespace android + +namespace mozilla { + namespace gfx { + class DataSourceSurface; + class SourceSurface; + } // namespace gfx + + namespace gl { + class GLBlitHelper; + class GLBlitTextureImageHelper; + class GLContext; + class GLLibraryEGL; + class GLReadTexImageHelper; + class GLScreenBuffer; + class SharedSurface; + class TextureGarbageBin; + struct SurfaceCaps; + } // namespace gl + + namespace layers { + class ColorTextureLayerProgram; + } // namespace layers +} // namespace mozilla + +namespace mozilla { +namespace gl { + +enum class GLFeature { + bind_buffer_offset, + blend_minmax, + clear_buffers, + copy_buffer, + depth_texture, + draw_buffers, + draw_instanced, + draw_range_elements, + 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, + get_string_indexed, + gpu_shader4, + instanced_arrays, + instanced_non_arrays, + internalformat_query, + invalidate_framebuffer, + map_buffer_range, + occlusion_query, + occlusion_query_boolean, + occlusion_query2, + packed_depth_stencil, + prim_restart, + prim_restart_fixed, + query_counter, + query_objects, + query_time_elapsed, + read_buffer, + renderbuffer_color_float, + renderbuffer_color_half_float, + robustness, + sRGB_framebuffer, + sRGB_texture, + sampler_objects, + seamless_cube_map_opt_in, + shader_texture_lod, + split_framebuffer, + standard_derivatives, + sync, + texture_3D, + texture_3D_compressed, + texture_3D_copy, + texture_float, + texture_float_linear, + texture_half_float, + texture_half_float_linear, + texture_non_power_of_two, + 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, + OpenGL, // only for IsAtLeast's <profile> parameter + OpenGLCore, + OpenGLCompatibility, + OpenGLES +}; + +enum class GLVendor { + Intel, + NVIDIA, + ATI, + Qualcomm, + Imagination, + Nouveau, + Vivante, + VMware, + ARM, + Other +}; + +enum class GLRenderer { + Adreno200, + Adreno205, + AdrenoTM200, + AdrenoTM205, + AdrenoTM305, + AdrenoTM320, + AdrenoTM330, + AdrenoTM420, + Mali400MP, + Mali450MP, + SGX530, + SGX540, + SGX544MP, + Tegra, + AndroidEmulator, + GalliumLlvmpipe, + IntelHD3000, + MicrosoftBasicRenderDriver, + Other +}; + +class GLContext + : public GLLibraryLoader + , public GenericAtomicRefCounted + , public SupportsWeakPtr<GLContext> +{ +public: + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext) + +// ----------------------------------------------------------------------------- +// basic enums +public: + +// ----------------------------------------------------------------------------- +// 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; + } + + /** + * 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; + } + + /** + * Return true if the context is a true OpenGL ES context or an ANGLE context + */ + inline bool IsGLES() const { + MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile"); + + return mProfile == ContextProfile::OpenGLES; + } + + static const char* GetProfileName(ContextProfile profile) + { + switch (profile) + { + case ContextProfile::OpenGL: + return "OpenGL"; + case ContextProfile::OpenGLCore: + return "OpenGL Core"; + case ContextProfile::OpenGLCompatibility: + return "OpenGL Compatibility"; + case ContextProfile::OpenGLES: + return "OpenGL ES"; + default: + break; + } + + MOZ_ASSERT(profile != ContextProfile::Unknown, "unknown context profile"); + return "OpenGL unknown profile"; + } + + /** + * Return true if we are running on a OpenGL core profile context + */ + const char* ProfileString() const { + return GetProfileName(mProfile); + } + + /** + * Return true if the context is compatible with given parameters + * + * IsAtLeast(ContextProfile::OpenGL, N) is exactly same as + * IsAtLeast(ContextProfile::OpenGLCore, N) || IsAtLeast(ContextProfile::OpenGLCompatibility, N) + */ + 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; + } + + if (profile == ContextProfile::OpenGL) { + return mProfile == ContextProfile::OpenGLCore || + mProfile == ContextProfile::OpenGLCompatibility; + } + + 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; + } + + const char* VersionString() const { + return mVersionString.get(); + } + + inline uint32_t ShadingLanguageVersion() const { + return mShadingLanguageVersion; + } + + GLVendor Vendor() const { + return mVendor; + } + + GLRenderer Renderer() const { + return mRenderer; + } + + bool IsContextLost() const { + return mContextLost; + } + + /** + * If this context is double-buffered, returns TRUE. + */ + virtual bool IsDoubleBuffered() const { + return false; + } + + virtual GLContextType GetContextType() const = 0; + + virtual bool IsCurrent() = 0; + + /** + * Get the default framebuffer for this context. + */ + virtual GLuint GetDefaultFramebuffer() { + return 0; + } + +protected: + bool mIsOffscreen; + bool mContextLost; + + /** + * 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; + nsCString mVersionString; + ContextProfile mProfile; + + uint32_t mShadingLanguageVersion; + + GLVendor mVendor; + GLRenderer mRenderer; + + void SetProfileVersion(ContextProfile profile, uint32_t version) { + MOZ_ASSERT(!mSymbols.fBindFramebuffer, + "SetProfileVersion can only be called before initialization!"); + MOZ_ASSERT(profile != ContextProfile::Unknown && + profile != ContextProfile::OpenGL, + "Invalid `profile` for SetProfileVersion"); + MOZ_ASSERT(version >= 100, "Invalid `version` for SetProfileVersion"); + + mVersion = version; + mProfile = profile; + } + + +// ----------------------------------------------------------------------------- +// 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). + */ +public: + + /** + * 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_texture_compression_dxt3, + ANGLE_texture_compression_dxt5, + ANGLE_timer_query, + APPLE_client_storage, + APPLE_framebuffer_multisample, + APPLE_sync, + APPLE_texture_range, + APPLE_vertex_array_object, + ARB_ES2_compatibility, + ARB_ES3_compatibility, + ARB_color_buffer_float, + 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_robustness, + ARB_sampler_objects, + ARB_seamless_cube_map, + ARB_shader_texture_lod, + ARB_sync, + ARB_texture_compression, + 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, + 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_draw_range_elements, + EXT_frag_depth, + EXT_framebuffer_blit, + EXT_framebuffer_multisample, + EXT_framebuffer_object, + EXT_framebuffer_sRGB, + EXT_gpu_shader4, + EXT_multisampled_render_to_texture, + EXT_occlusion_query_boolean, + EXT_packed_depth_stencil, + EXT_read_format_bgra, + EXT_robustness, + EXT_sRGB, + EXT_sRGB_write_control, + EXT_shader_texture_lod, + EXT_texture3D, + EXT_texture_compression_dxt1, + EXT_texture_compression_s3tc, + EXT_texture_filter_anisotropic, + EXT_texture_format_BGRA8888, + 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, + 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_element_index_uint, + 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, + 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); + +// ----------------------------------------------------------------------------- +// Robustness handling +private: + /** + * The derived class is expected to provide information on whether or not it + * supports robustness. + */ + virtual bool SupportsRobustness() const = 0; + +public: +// ----------------------------------------------------------------------------- +// Error handling + static const char* GLErrorToString(GLenum aError) { + switch (aError) { + 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"; + default: + return ""; + } + } + +private: + GLenum mTopError; + + GLenum RawGetError() { + return mSymbols.fGetError(); + } + + GLenum RawGetErrorAndClear() { + GLenum err = RawGetError(); + + if (err) + while (RawGetError()) {} + + return err; + } + +public: + GLenum FlushErrors() { + GLenum err = RawGetErrorAndClear(); + if (!mTopError) + mTopError = err; + return err; + } + + // 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. + GLenum fGetError() { + FlushErrors(); + + GLenum err = mTopError; + mTopError = LOCAL_GL_NO_ERROR; + return err; + } + + //////////////////////////////////// + // Use this safer option. + class LocalErrorScope; + +private: + std::stack<const LocalErrorScope*> mLocalErrorScopeStack; + +public: + class LocalErrorScope { + GLContext& mGL; + GLenum mOldTop; + bool mHasBeenChecked; + + public: + explicit LocalErrorScope(GLContext& gl) + : mGL(gl) + , mHasBeenChecked(false) + { + mGL.mLocalErrorScopeStack.push(this); + + mGL.FlushErrors(); + + mOldTop = mGL.mTopError; + mGL.mTopError = LOCAL_GL_NO_ERROR; + } + + GLenum GetError() { + MOZ_ASSERT(!mHasBeenChecked); + mHasBeenChecked = true; + + const GLenum ret = mGL.fGetError(); + + while (mGL.fGetError()) {} + + return ret; + } + + ~LocalErrorScope() { + MOZ_ASSERT(mHasBeenChecked); + + MOZ_ASSERT(mGL.fGetError() == LOCAL_GL_NO_ERROR); + + 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; + } + +private: + static void GLAPIENTRY StaticDebugCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const GLvoid* userParam); + void DebugCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message); + + +// ----------------------------------------------------------------------------- +// MOZ_GL_DEBUG implementation +private: + +#undef BEFORE_GL_CALL +#undef AFTER_GL_CALL + +#ifdef MOZ_GL_DEBUG + +#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 + + void BeforeGLCall(const char* funcName) { + MOZ_ASSERT(IsCurrent()); + + if (mDebugFlags) { + FlushErrors(); + + if (mDebugFlags & DebugFlagTrace) { + printf_stderr("[gl:%p] > %s\n", this, funcName); + } + + GLContext* tlsContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS); + if (this != tlsContext) { + printf_stderr("Fatal: %s called on non-current context %p. The" + " current context for this thread is %p.\n", + funcName, this, tlsContext); + MOZ_CRASH("GFX: GLContext is not current."); + } + } + } + + void AfterGLCall(const char* funcName) { + if (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(); + GLenum err = FlushErrors(); + + if (mDebugFlags & DebugFlagTrace) { + printf_stderr("[gl:%p] < %s [%s (0x%04x)]\n", this, funcName, + GLErrorToString(err), err); + } + + if (err != LOCAL_GL_NO_ERROR && + !mLocalErrorScopeStack.size()) + { + printf_stderr("[gl:%p] %s: Generated unexpected %s error." + " (0x%04x)\n", this, funcName, + GLErrorToString(err), err); + + if (mDebugFlags & DebugFlagAbortOnError) { + MOZ_CRASH("Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run" + " with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)"); + } + } + } + } + + GLContext* TrackingContext() + { + GLContext* tip = this; + while (tip->mSharedContext) + tip = tip->mSharedContext; + return tip; + } + + static void AssertNotPassingStackBufferToTheGL(const void* ptr); + +#ifdef MOZ_WIDGET_ANDROID +// Record the name of the GL call for better hang stacks on Android. +#define BEFORE_GL_CALL \ + PROFILER_LABEL_FUNC( \ + js::ProfileEntry::Category::GRAPHICS);\ + BeforeGLCall(MOZ_FUNCTION_NAME) +#else +#define BEFORE_GL_CALL \ + do { \ + BeforeGLCall(MOZ_FUNCTION_NAME); \ + } while (0) +#endif + +#define AFTER_GL_CALL \ + do { \ + AfterGLCall(MOZ_FUNCTION_NAME); \ + } while (0) + +#define TRACKING_CONTEXT(a) \ + do { \ + TrackingContext()->a; \ + } while (0) + +#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) AssertNotPassingStackBufferToTheGL(ptr) + +#else // ifdef MOZ_GL_DEBUG + +#ifdef MOZ_WIDGET_ANDROID +// Record the name of the GL call for better hang stacks on Android. +#define BEFORE_GL_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS) +#else +#define BEFORE_GL_CALL do { } while (0) +#endif +#define AFTER_GL_CALL do { } while (0) +#define TRACKING_CONTEXT(a) do {} while (0) +#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) do {} while (0) + +#endif // ifdef MOZ_GL_DEBUG + +#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) + + // 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(); + + // 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() { } + + +// ----------------------------------------------------------------------------- +// GL official entry points +public: + + 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 fBindFramebuffer(GLenum target, GLuint framebuffer); + + 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); + 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(); + 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); + 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); + AFTER_GL_CALL; + } + + void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) { + BEFORE_GL_CALL; + mSymbols.fGetAttachedShaders(program, maxCount, count, shaders); + AFTER_GL_CALL; + } + + GLint fGetAttribLocation(GLuint program, const GLchar* name) { + BEFORE_GL_CALL; + GLint retval = mSymbols.fGetAttribLocation(program, name); + AFTER_GL_CALL; + return retval; + } + +private: + void raw_fGetIntegerv(GLenum pname, GLint* params) { + BEFORE_GL_CALL; + mSymbols.fGetIntegerv(pname, params); + AFTER_GL_CALL; + } + +public: + + void fGetIntegerv(GLenum pname, GLint* params); + + void GetUIntegerv(GLenum pname, GLuint* params) { + fGetIntegerv(pname, reinterpret_cast<GLint*>(params)); + } + + template<typename T> + T GetIntAs(GLenum pname) { + static_assert(sizeof(T) == sizeof(GLint), "Invalid T."); + T ret = 0; + fGetIntegerv(pname, (GLint*)&ret); + return ret; + } + + void fGetFloatv(GLenum pname, GLfloat* params) { + BEFORE_GL_CALL; + mSymbols.fGetFloatv(pname, params); + AFTER_GL_CALL; + } + + void fGetBooleanv(GLenum pname, realGLboolean* params) { + BEFORE_GL_CALL; + mSymbols.fGetBooleanv(pname, params); + AFTER_GL_CALL; + } + + void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { + BEFORE_GL_CALL; + mSymbols.fGetBufferParameteriv(target, pname, params); + AFTER_GL_CALL; + } + + GLuint fGetDebugMessageLog(GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetDebugMessageLog); + GLuint ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids, severities, lengths, messageLog); + AFTER_GL_CALL; + return ret; + } + + void fGetPointerv(GLenum pname, GLvoid** params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetPointerv); + mSymbols.fGetPointerv(pname, params); + 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); + 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); + 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); + AFTER_GL_CALL; + } + + void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) { + BEFORE_GL_CALL; + mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog); + 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) { + BEFORE_GL_CALL; + const GLubyte* result = mSymbols.fGetString(name); + 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); + 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); + AFTER_GL_CALL; + } + + void fGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { + BEFORE_GL_CALL; + mSymbols.fGetTexParameterfv(target, pname, params); + AFTER_GL_CALL; + } + + void fGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { + BEFORE_GL_CALL; + mSymbols.fGetTexParameteriv(target, pname, params); + AFTER_GL_CALL; + } + + void fGetUniformfv(GLuint program, GLint location, GLfloat* params) { + BEFORE_GL_CALL; + mSymbols.fGetUniformfv(program, location, params); + AFTER_GL_CALL; + } + + void fGetUniformiv(GLuint program, GLint location, GLint* params) { + BEFORE_GL_CALL; + mSymbols.fGetUniformiv(program, location, params); + AFTER_GL_CALL; + } + + void fGetUniformuiv(GLuint program, GLint location, GLuint* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetUniformuiv); + mSymbols.fGetUniformuiv(program, location, params); + AFTER_GL_CALL; + } + + GLint fGetUniformLocation (GLint programObj, const GLchar* name) { + BEFORE_GL_CALL; + GLint retval = mSymbols.fGetUniformLocation(programObj, name); + AFTER_GL_CALL; + return retval; + } + + void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) { + BEFORE_GL_CALL; + mSymbols.fGetVertexAttribfv(index, pname, retval); + AFTER_GL_CALL; + } + + void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) { + BEFORE_GL_CALL; + mSymbols.fGetVertexAttribiv(index, pname, retval); + AFTER_GL_CALL; + } + + void fGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** retval) { + BEFORE_GL_CALL; + mSymbols.fGetVertexAttribPointerv(index, pname, retval); + AFTER_GL_CALL; + } + + void fHint(GLenum target, GLenum mode) { + BEFORE_GL_CALL; + mSymbols.fHint(target, mode); + AFTER_GL_CALL; + } + + realGLboolean fIsBuffer(GLuint buffer) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsBuffer(buffer); + AFTER_GL_CALL; + return retval; + } + + realGLboolean fIsEnabled(GLenum capability) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsEnabled(capability); + AFTER_GL_CALL; + return retval; + } + + realGLboolean fIsProgram(GLuint program) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsProgram(program); + AFTER_GL_CALL; + return retval; + } + + realGLboolean fIsShader(GLuint shader) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsShader(shader); + AFTER_GL_CALL; + return retval; + } + + realGLboolean fIsTexture(GLuint texture) { + BEFORE_GL_CALL; + realGLboolean 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 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) { + ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels); + BEFORE_GL_CALL; + mSymbols.fReadPixels(x, y, width, height, format, type, pixels); + 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 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); + AFTER_GL_CALL; + } + + void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) { + BEFORE_GL_CALL; + mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog); + 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); + 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); + 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: + friend class SharedSurface; + + void raw_fBindFramebuffer(GLenum target, GLuint framebuffer) { + BEFORE_GL_CALL; + mSymbols.fBindFramebuffer(target, framebuffer); + AFTER_GL_CALL; + } + +public: + void fBindRenderbuffer(GLenum target, GLuint renderbuffer) { + BEFORE_GL_CALL; + mSymbols.fBindRenderbuffer(target, renderbuffer); + AFTER_GL_CALL; + } + + GLenum fCheckFramebufferStatus(GLenum target) { + BEFORE_GL_CALL; + GLenum retval = mSymbols.fCheckFramebufferStatus(target); + 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; + if (mNeedsCheckAfterAttachTextureToFb) { + fCheckFramebufferStatus(target); + } + } + + 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); + AFTER_GL_CALL; + } + + void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) { + BEFORE_GL_CALL; + mSymbols.fGetRenderbufferParameteriv(target, pname, value); + AFTER_GL_CALL; + } + + realGLboolean fIsFramebuffer (GLuint framebuffer) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer); + AFTER_GL_CALL; + return retval; + } + +public: + realGLboolean fIsRenderbuffer (GLuint renderbuffer) { + BEFORE_GL_CALL; + realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer); + 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) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fMapBuffer); + void* ret = mSymbols.fMapBuffer(target, access); + AFTER_GL_CALL; + return ret; + } + + realGLboolean fUnmapBuffer(GLenum target) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fUnmapBuffer); + realGLboolean ret = mSymbols.fUnmapBuffer(target); + AFTER_GL_CALL; + return ret; + } + + +private: + GLuint raw_fCreateProgram() { + BEFORE_GL_CALL; + GLuint ret = mSymbols.fCreateProgram(); + AFTER_GL_CALL; + return ret; + } + + GLuint raw_fCreateShader(GLenum t) { + BEFORE_GL_CALL; + GLuint ret = mSymbols.fCreateShader(t); + AFTER_GL_CALL; + return ret; + } + + void raw_fGenBuffers(GLsizei n, GLuint* names) { + BEFORE_GL_CALL; + mSymbols.fGenBuffers(n, names); + AFTER_GL_CALL; + } + + void raw_fGenFramebuffers(GLsizei n, GLuint* names) { + BEFORE_GL_CALL; + mSymbols.fGenFramebuffers(n, names); + AFTER_GL_CALL; + } + + void raw_fGenRenderbuffers(GLsizei n, GLuint* names) { + BEFORE_GL_CALL; + mSymbols.fGenRenderbuffers(n, names); + AFTER_GL_CALL; + } + + void raw_fGenTextures(GLsizei n, GLuint* names) { + BEFORE_GL_CALL; + mSymbols.fGenTextures(n, names); + 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; + } + + 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) { + raw_fDeleteTextures(n, names); + TRACKING_CONTEXT(DeletedTextures(this, n, names)); + } + + GLenum fGetGraphicsResetStatus() { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetGraphicsResetStatus); + GLenum ret = mSymbols.fGetGraphicsResetStatus(); + AFTER_GL_CALL; + return ret; + } + + +// ----------------------------------------------------------------------------- +// Extension ARB_sync (GL) +public: + GLsync fFenceSync(GLenum condition, GLbitfield flags) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fFenceSync); + GLsync ret = mSymbols.fFenceSync(condition, flags); + AFTER_GL_CALL; + return ret; + } + + realGLboolean fIsSync(GLsync sync) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fIsSync); + realGLboolean ret = mSymbols.fIsSync(sync); + 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) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fClientWaitSync); + GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout); + 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); + 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; + } + +// ----------------------------------------------------------------------------- +// Feature draw_range_elements +public: + void fDrawRangeElements(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid* indices) + { + BeforeGLDrawCall(); + raw_fDrawRangeElements(mode, start, end, count, type, indices); + AfterGLDrawCall(); + } + +private: + void raw_fDrawRangeElements(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid* indices) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fDrawRangeElements); + mSymbols.fDrawRangeElements(mode, start, end, count, type, indices); + 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); + AFTER_GL_CALL; + } + + void fGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) + { + ASSERT_SYMBOL_PRESENT(fGetVertexAttribIuiv); + BEFORE_GL_CALL; + mSymbols.fGetVertexAttribIuiv(index, pname, params); + 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) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetFragDataLocation); + GLint result = mSymbols.fGetFragDataLocation(program, name); + 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); + 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); + AFTER_GL_CALL; + } + + void fGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetQueryObjectuiv); + mSymbols.fGetQueryObjectuiv(id, pname, params); + AFTER_GL_CALL; + } + + realGLboolean fIsQuery(GLuint query) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fIsQuery); + realGLboolean retval = mSymbols.fIsQuery(query); + 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); + AFTER_GL_CALL; + } + + void fGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetQueryObjectui64v); + mSymbols.fGetQueryObjectui64v(id, pname, params); + 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); + 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); + 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) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fIsTransformFeedback); + realGLboolean result = mSymbols.fIsTransformFeedback(id); + 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); + 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); + 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); + 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) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fIsVertexArray); + realGLboolean ret = mSymbols.fIsVertexArray(array); + 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) + { + ASSERT_SYMBOL_PRESENT(fTestFence); + BEFORE_GL_CALL; + realGLboolean ret = mSymbols.fTestFence(fence); + AFTER_GL_CALL; + return ret; + } + + void fFinishFence(GLuint fence) + { + ASSERT_SYMBOL_PRESENT(fFinishFence); + BEFORE_GL_CALL; + mSymbols.fFinishFence(fence); + AFTER_GL_CALL; + } + + realGLboolean fIsFence(GLuint fence) + { + ASSERT_SYMBOL_PRESENT(fIsFence); + BEFORE_GL_CALL; + realGLboolean ret = mSymbols.fIsFence(fence); + 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); + 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) + { + ASSERT_SYMBOL_PRESENT(fMapBufferRange); + BEFORE_GL_CALL; + void* data = mSymbols.fMapBufferRange(target, offset, length, access); + 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) + { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fIsSampler); + realGLboolean result = mSymbols.fIsSampler(sampler); + 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); + 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); + AFTER_GL_CALL; + } + + GLuint fGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) { + ASSERT_SYMBOL_PRESENT(fGetUniformBlockIndex); + BEFORE_GL_CALL; + GLuint result = mSymbols.fGetUniformBlockIndex(program, uniformBlockName); + 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); + 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); + 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); + 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); + 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); + 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); + 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; + } + +// ----------------------------------------------------------------------------- +// get_string_indexed + + const GLubyte* fGetStringi(GLenum name, GLuint index) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fGetStringi); + const GLubyte* ret = mSymbols.fGetStringi(name, index); + AFTER_GL_CALL; + return ret; + } + +// ----------------------------------------------------------------------------- +// APPLE_framebuffer_multisample + + void fResolveMultisampleFramebufferAPPLE() { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fResolveMultisampleFramebufferAPPLE); + mSymbols.fResolveMultisampleFramebufferAPPLE(); + AFTER_GL_CALL; + } + +// ----------------------------------------------------------------------------- +// prim_restart + + void fPrimitiveRestartIndex(GLuint index) { + BEFORE_GL_CALL; + ASSERT_SYMBOL_PRESENT(fPrimitiveRestartIndex); + mSymbols.fPrimitiveRestartIndex(index); + AFTER_GL_CALL; + } + +// ----------------------------------------------------------------------------- +// Constructor +protected: + explicit GLContext(CreateContextFlags flags, const SurfaceCaps& caps, + GLContext* sharedContext = nullptr, + bool isOffscreen = false); + + +// ----------------------------------------------------------------------------- +// Destructor +public: + virtual ~GLContext(); + + // Mark this context as destroyed. This will nullptr out all + // the GL function pointers! + void MarkDestroyed(); + +// ----------------------------------------------------------------------------- +// Everything that isn't standard GL APIs +protected: + typedef gfx::SurfaceFormat SurfaceFormat; + + virtual bool MakeCurrentImpl(bool aForce) = 0; + +public: +#ifdef MOZ_GL_DEBUG + static void StaticInit() { + PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, nullptr); + } +#endif + + bool MakeCurrent(bool aForce = false) { + if (IsDestroyed()) { + return false; + } +#ifdef MOZ_GL_DEBUG + PR_SetThreadPrivate(sCurrentGLContextTLS, this); + + // XXX this assertion is disabled because it's triggering on Mac; + // we need to figure out why and reenable it. +#if 0 + // IsOwningThreadCurrent is a bit of a misnomer; + // the "owning thread" is the creation thread, + // and the only thread that can own this. We don't + // support contexts used on multiple threads. + NS_ASSERTION(IsOwningThreadCurrent(), + "MakeCurrent() called on different thread than this context was created on!"); +#endif +#endif + return MakeCurrentImpl(aForce); + } + + virtual bool Init() = 0; + + virtual bool SetupLookupFunction() = 0; + + virtual void ReleaseSurface() {} + + bool IsDestroyed() { + // MarkDestroyed will mark all these as null. + return mSymbols.fUseProgram == nullptr; + } + + GLContext* GetSharedContext() { return mSharedContext; } + + /** + * Returns true if the thread on which this context was created is the currently + * executing thread. + */ + bool IsOwningThreadCurrent(); + + 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; } + + /** + * 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; } + + // Before reads from offscreen texture + void GuaranteeResolve(); + + /* + * Resize the current offscreen buffer. Returns true on success. + * If it returns false, the context should be treated as unusable + * and should be recreated. After the resize, the viewport is not + * changed; glViewport should be called as appropriate. + * + * Only valid if IsOffscreen() returns true. + */ + bool ResizeOffscreen(const gfx::IntSize& size) { + return ResizeScreenBuffer(size); + } + + /* + * Return size of this offscreen context. + * + * Only valid if IsOffscreen() returns true. + */ + const gfx::IntSize& OffscreenSize() const; + + void BindFB(GLuint fb) { + fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb); + MOZ_ASSERT(!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(); + + GLuint GetReadFB(); + + GLuint GetFB(); + +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: + + void ForceDirtyScreen(); + void CleanDirtyScreen(); + + virtual GLenum GetPreferredARGB32Format() const { return LOCAL_GL_RGBA; } + + virtual GLenum GetPreferredEGLImageTextureTarget() const { + return IsExtensionSupported(OES_EGL_image_external) ? + LOCAL_GL_TEXTURE_EXTERNAL : LOCAL_GL_TEXTURE_2D; + } + + virtual bool RenewSurface(nsIWidget* aWidget) { return false; } + + // Shared code for GL extensions and GLX extensions. + static bool ListHasExtension(const GLubyte* extensions, + const char* extension); + + GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; } + +public: + std::map<GLuint, SharedSurface*> mFBOMapping; + + enum { + DebugFlagEnabled = 1 << 0, + DebugFlagTrace = 1 << 1, + DebugFlagAbortOnError = 1 << 2 + }; + + const uint8_t mDebugFlags; + +protected: + RefPtr<GLContext> mSharedContext; + + // The thread id which this context was created. + PlatformThreadId mOwningThreadId; + + GLContextSymbols mSymbols; + +#ifdef MOZ_GL_DEBUG + // Non-zero debug flags will check that we don't send call + // to a GLContext that isn't current on the current + // thread. + // Store the current context when binding to thread local + // storage to support debug flags on an arbitrary thread. + static unsigned sCurrentGLContextTLS; +#endif + + UniquePtr<GLBlitHelper> mBlitHelper; + UniquePtr<GLReadTexImageHelper> mReadTexImageHelper; + +public: + GLBlitHelper* BlitHelper(); + GLBlitTextureImageHelper* BlitTextureImageHelper(); + 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 InitOffscreen(const gfx::IntSize& size, const SurfaceCaps& caps); + +protected: + // Note that it does -not- clear the resized buffers. + bool CreateScreenBuffer(const gfx::IntSize& size, const SurfaceCaps& caps) { + if (!IsOffscreenSizeAllowed(size)) + return false; + + return CreateScreenBufferImpl(size, caps); + } + + bool CreateScreenBufferImpl(const gfx::IntSize& size, + const SurfaceCaps& caps); + +public: + bool ResizeScreenBuffer(const gfx::IntSize& size); + +protected: + SurfaceCaps mCaps; + +public: + const SurfaceCaps& Caps() const { + return mCaps; + } + + // Only varies based on bpp16 and alpha. + GLFormats ChooseGLFormats(const SurfaceCaps& caps) const; + + 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: + friend class GLScreenBuffer; + UniquePtr<GLScreenBuffer> mScreen; + + SharedSurface* mLockedSurface; + +public: + void LockSurface(SharedSurface* surf) { + MOZ_ASSERT(!mLockedSurface); + mLockedSurface = surf; + } + + void UnlockSurface(SharedSurface* surf) { + MOZ_ASSERT(mLockedSurface == surf); + mLockedSurface = nullptr; + } + + SharedSurface* GetLockedSurface() const { + return mLockedSurface; + } + + bool IsOffscreen() const { + return mIsOffscreen; + } + + GLScreenBuffer* Screen() const { + return mScreen.get(); + } + + /* Clear to transparent black, with 0 depth and stencil, + * while preserving current ClearColor etc. values. + * Useful for resizing offscreen buffers. + */ + void ClearSafely(); + + bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; } + + bool IsDrawingToDefaultFramebuffer(); + +protected: + RefPtr<TextureGarbageBin> mTexGarbageBin; + +public: + TextureGarbageBin* TexGarbageBin() { + MOZ_ASSERT(mTexGarbageBin); + return mTexGarbageBin; + } + + void EmptyTexGarbageBin(); + + bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const; + +protected: + bool InitWithPrefix(const char* prefix, bool trygl); + +private: + bool InitWithPrefixImpl(const char* prefix, bool trygl); + void LoadMoreSymbols(const char* prefix, bool trygl); + bool LoadExtSymbols(const char* prefix, bool trygl, const SymLoadStruct* list, + GLExtensions ext); + bool LoadFeatureSymbols(const char* prefix, bool trygl, const SymLoadStruct* list, + GLFeature feature); + +protected: + void InitExtensions(); + + GLint mViewportRect[4]; + GLint mScissorRect[4]; + + GLint mMaxTextureSize; + GLint mMaxCubeMapTextureSize; + GLint mMaxTextureImageSize; + GLint mMaxRenderbufferSize; + GLint mMaxViewportDims[2]; + GLsizei mMaxSamples; + bool mNeedsTextureSizeChecks; + bool mNeedsFlushBeforeDeleteFB; + bool mTextureAllocCrashesOnMapFailure; + bool mNeedsCheckAfterAttachTextureToFb; + bool mWorkAroundDriverBugs; + + 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: + GLsizei MaxSamples() const { + return mMaxSamples; + } + + 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; + } + +#undef ASSERT_SYMBOL_PRESENT + +#ifdef MOZ_GL_DEBUG + 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; + +public: + void FlushIfHeavyGLCallsSinceLastFlush(); + static bool ShouldSpew(); + static bool ShouldDumpExts(); + void Readback(SharedSurface* src, gfx::DataSourceSurface* dest); +}; + +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 ? "(*)" : ""); + } +} + +/** + * 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. + */ +GLuint CreateTextureForOffscreen(GLContext* aGL, const GLFormats& aFormats, + const gfx::IntSize& aSize); + +/** + * Helper function that creates a 2D texture aSize.width x aSize.height with + * storage type aInternalFormat. Returns GL texture object id. + * + * Initialize textyre parameters to: + * GL_TEXTURE_MIN_FILTER = GL_LINEAR + * GL_TEXTURE_MAG_FILTER = GL_LINEAR + * GL_TEXTURE_WRAP_S = GL_CLAMP_TO_EDGE + * GL_TEXTURE_WRAP_T = GL_CLAMP_TO_EDGE + */ +GLuint CreateTexture(GLContext* aGL, GLenum aInternalFormat, GLenum aFormat, + GLenum aType, const gfx::IntSize& aSize, bool linear = true); + +/** + * 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); + +} /* 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..12da90aeed --- /dev/null +++ b/gfx/gl/GLContextCGL.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 + +namespace mozilla { +namespace gl { + +class GLContextCGL : public GLContext +{ + friend class GLContextProviderCGL; + + NSOpenGLContext* mContext; + +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override) + GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps, + NSOpenGLContext* context, bool isOffscreen, ContextProfile profile); + + ~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); + } + + bool Init() override; + + NSOpenGLContext* GetNSOpenGLContext() const { return mContext; } + CGLContextObj GetCGLContext() const; + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + virtual GLenum GetPreferredARGB32Format() const override; + + virtual bool SetupLookupFunction() override; + + virtual bool IsDoubleBuffered() const override; + + virtual bool SupportsRobustness() const override { return false; } + + virtual bool SwapBuffers() 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..86e9a5b98b --- /dev/null +++ b/gfx/gl/GLContextEAGL.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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(CreateContextFlags flags, const SurfaceCaps& caps, EAGLContext* context, + GLContext* sharedContext, bool isOffscreen, 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 Init() override; + + bool AttachToWindow(nsIWidget* aWidget); + + EAGLContext* GetEAGLContext() const { return mContext; } + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + virtual bool SetupLookupFunction() override; + + virtual bool IsDoubleBuffered() const override; + + virtual bool SupportsRobustness() const override { return false; } + + virtual bool SwapBuffers() override; + + virtual GLuint GetDefaultFramebuffer() override { + return mBackbufferFB; + } + + virtual bool RenewSurface(nsIWidget* aWidget) override { + // FIXME: should use the passed widget instead of the existing one. + return RecreateRB(); + } + +private: + GLuint mBackbufferRB; + GLuint mBackbufferFB; + + void* mLayer; + + 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..9755ecfe79 --- /dev/null +++ b/gfx/gl/GLContextEGL.h @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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" + +namespace mozilla { +namespace gl { + +class GLContextEGL : public GLContext +{ + friend class TextureImageEGL; + + static already_AddRefed<GLContextEGL> + CreateGLContext(CreateContextFlags flags, + const SurfaceCaps& caps, + GLContextEGL* shareContext, + bool isOffscreen, + EGLConfig config, + EGLSurface surface, + nsACString* const out_failureId); + +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override) + GLContextEGL(CreateContextFlags flags, + const SurfaceCaps& caps, + GLContext* shareContext, + bool isOffscreen, + EGLConfig config, + EGLSurface surface, + EGLContext context); + + ~GLContextEGL(); + + virtual GLContextType GetContextType() const override { return GLContextType::EGL; } + + static GLContextEGL* Cast(GLContext* gl) { + MOZ_ASSERT(gl->GetContextType() == GLContextType::EGL); + return static_cast<GLContextEGL*>(gl); + } + + static EGLSurface CreateSurfaceForWindow(nsIWidget* aWidget); + + static void DestroySurface(EGLSurface aSurface); + + bool Init() override; + + virtual bool IsDoubleBuffered() const override { + return mIsDoubleBuffered; + } + + void SetIsDoubleBuffered(bool aIsDB) { + mIsDoubleBuffered = aIsDB; + } + + virtual bool SupportsRobustness() const override { + return sEGLLibrary.HasRobustness(); + } + + virtual bool IsANGLE() const override { + return sEGLLibrary.IsANGLE(); + } + + virtual bool IsWARP() const override { + return sEGLLibrary.IsWARP(); + } + + virtual bool BindTexImage() override; + + virtual bool ReleaseTexImage() override; + + void SetEGLSurfaceOverride(EGLSurface surf); + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + virtual bool RenewSurface(nsIWidget* aWidget) override; + + virtual void ReleaseSurface() override; + + virtual bool SetupLookupFunction() override; + + virtual bool SwapBuffers() override; + + // hold a reference to the given surface + // for the lifetime of this context. + void HoldSurface(gfxASurface* aSurf); + + EGLSurface GetEGLSurface() const { + return mSurface; + } + + EGLDisplay GetEGLDisplay() const { + return sEGLLibrary.Display(); + } + + bool BindTex2DOffscreen(GLContext* aOffscreen); + void UnbindTex2DOffscreen(GLContext* aOffscreen); + void BindOffscreenFramebuffer(); + + static already_AddRefed<GLContextEGL> + CreateEGLPBufferOffscreenContext(CreateContextFlags flags, + const gfx::IntSize& size, + const SurfaceCaps& minCaps, + nsACString* const out_FailureId); + +protected: + friend class GLContextProviderEGL; + +public: + const EGLConfig mConfig; +protected: + EGLSurface mSurface; +public: + const EGLContext mContext; +protected: + EGLSurface mSurfaceOverride; + RefPtr<gfxASurface> mThebesSurface; + bool mBound; + + bool mIsPBuffer; + bool mIsDoubleBuffered; + bool mCanBindToTexture; + bool mShareWithEGLImage; + bool mOwnsContext; + + static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config, + EGLenum bindToTextureFormat, + gfx::IntSize& pbsize); +}; + +} // 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..0714d96415 --- /dev/null +++ b/gfx/gl/GLContextFeatures.cpp @@ -0,0 +1,928 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "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_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 + } + }, + { + "draw_range_elements", + GLVersion::GL1_2, + GLESVersion::ES3, + GLContext::Extension_None, + { + GLContext::EXT_draw_range_elements, + 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::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). + */ + }, + { + "get_string_indexed", + GLVersion::GL3, + GLESVersion::ES3, + GLContext::Extension_None, + { + GLContext::Extensions_End + } + // glGetStringi + }, + { + "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::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 + } + }, + { + "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::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 + } + }, + { + "robustness", + GLVersion::NONE, + GLESVersion::NONE, + GLContext::Extension_None, + { + GLContext::ARB_robustness, + GLContext::EXT_robustness, + GLContext::Extensions_End + } + }, + { + "sRGB_framebuffer", + GLVersion::GL3, + GLESVersion::ES3, + GLContext::ARB_framebuffer_sRGB, + { + GLContext::EXT_framebuffer_sRGB, + GLContext::EXT_sRGB_write_control, + GLContext::Extensions_End + } + }, + { + "sRGB_texture", + GLVersion::GL2_1, + GLESVersion::ES3, + GLContext::Extension_None, + { + GLContext::EXT_sRGB, + GLContext::EXT_texture_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::NONE, + GLESVersion::NONE, + 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::EXT_texture3D, + 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_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::ES3, + 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_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; +} + +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..ca476baec0 --- /dev/null +++ b/gfx/gl/GLContextGLX.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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(CreateContextFlags flags, + const SurfaceCaps& caps, + GLContextGLX* shareContext, + bool isOffscreen, + Display* display, + GLXDrawable drawable, + GLXFBConfig cfg, + bool deleteDrawable, + gfxXlibSurface* pixmap = nullptr, + ContextProfile profile = ContextProfile::OpenGLCompatibility); + + // Finds a GLXFBConfig compatible with the provided window. + static bool + FindFBConfigForWindow(Display* display, int screen, Window window, + ScopedXFree<GLXFBConfig>* const out_scopedConfigArr, + GLXFBConfig* const out_config, int* const out_visid); + + ~GLContextGLX(); + + virtual 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; + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + virtual bool SetupLookupFunction() override; + + virtual bool IsDoubleBuffered() const override; + + virtual bool SupportsRobustness() const override; + + virtual bool SwapBuffers() 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(CreateContextFlags flags, + const SurfaceCaps& caps, + GLContext* shareContext, + bool isOffscreen, + Display* aDisplay, + GLXDrawable aDrawable, + GLXContext aContext, + bool aDeleteDrawable, + bool aDoubleBuffered, + gfxXlibSurface* aPixmap, + ContextProfile profile); + + GLXContext mContext; + Display* mDisplay; + GLXDrawable mDrawable; + bool mDeleteDrawable; + bool mDoubleBuffered; + + GLXLibrary* mGLX; + + RefPtr<gfxXlibSurface> mPixmap; + bool mOwnsContext; +}; + +} +} + +#endif // GLCONTEXTGLX_H_ diff --git a/gfx/gl/GLContextProvider.h b/gfx/gl/GLContextProvider.h new file mode 100644 index 0000000000..6e096c1f7e --- /dev/null +++ b/gfx/gl/GLContextProvider.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 GLCONTEXTPROVIDER_H_ +#define GLCONTEXTPROVIDER_H_ + +#include "GLContextTypes.h" +#include "SurfaceTypes.h" + +#include "nsSize.h" // for gfx::IntSize (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 + +#if defined(MOZ_X11) + #define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX + #include "GLContextProviderImpl.h" + #undef GL_CONTEXT_PROVIDER_NAME + #define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX +#endif + +#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL +#include "GLContextProviderImpl.h" +#undef GL_CONTEXT_PROVIDER_NAME +#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..0b8add435a --- /dev/null +++ b/gfx/gl/GLContextProviderCGL.mm @@ -0,0 +1,400 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "GLContextProvider.h" +#include "GLContextCGL.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include <OpenGL/gl.h> +#include "gfxFailure.h" +#include "gfxPrefs.h" +#include "prenv.h" +#include "GeckoProfiler.h" +#include "mozilla/gfx/MacIOSurface.h" +#include "mozilla/widget/CompositorWidget.h" + +#include <OpenGL/OpenGL.h> + +// When running inside a VM, creating an accelerated OpenGL context usually +// fails. Uncomment this line to emulate that behavior. +// #define EMULATE_VM + +namespace mozilla { +namespace gl { + +using namespace mozilla::gfx; +using namespace mozilla::widget; + +class CGLLibrary +{ +public: + CGLLibrary() + : mInitialized(false) + , mUseDoubleBufferedWindows(true) + , mOGLLibrary(nullptr) + {} + + 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; + } + } + + const char* db = PR_GetEnv("MOZ_CGL_DB"); + if (db) { + mUseDoubleBufferedWindows = *db != '0'; + } + + mInitialized = true; + return true; + } + + bool UseDoubleBufferedWindows() const { + MOZ_ASSERT(mInitialized); + return mUseDoubleBufferedWindows; + } + +private: + bool mInitialized; + bool mUseDoubleBufferedWindows; + PRLibrary* mOGLLibrary; +}; + +CGLLibrary sCGLLibrary; + +GLContextCGL::GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps, + NSOpenGLContext* context, bool isOffscreen, + ContextProfile profile) + : GLContext(flags, caps, nullptr, isOffscreen) + , mContext(context) +{ + SetProfileVersion(profile, 210); +} + +GLContextCGL::~GLContextCGL() +{ + MarkDestroyed(); + + 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]; + } + +} + +bool +GLContextCGL::Init() +{ + if (!InitWithPrefix("gl", true)) + return false; + + return true; +} + +CGLContextObj +GLContextCGL::GetCGLContext() const +{ + return static_cast<CGLContextObj>([mContext CGLContextObj]); +} + +bool +GLContextCGL::MakeCurrentImpl(bool aForce) +{ + if (!aForce && [NSOpenGLContext currentContext] == mContext) { + return true; + } + + if (mContext) { + [mContext makeCurrentContext]; + MOZ_ASSERT(IsCurrent()); + // 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 = gfxPrefs::LayoutFrameRate() == 0 ? 0 : 1; + [mContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; + } + return true; +} + +bool +GLContextCGL::IsCurrent() { + return [NSOpenGLContext currentContext] == mContext; +} + +GLenum +GLContextCGL::GetPreferredARGB32Format() const +{ + return LOCAL_GL_BGRA; +} + +bool +GLContextCGL::SetupLookupFunction() +{ + return false; +} + +bool +GLContextCGL::IsDoubleBuffered() const +{ + return sCGLLibrary.UseDoubleBufferedWindows(); +} + +bool +GLContextCGL::SwapBuffers() +{ + PROFILER_LABEL("GLContextCGL", "SwapBuffers", + js::ProfileEntry::Category::GRAPHICS); + + [mContext flushBuffer]; + return true; +} + + +already_AddRefed<GLContext> +GLContextProviderCGL::CreateWrappingExisting(void*, void*) +{ + return nullptr; +} + +static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered[] = { + NSOpenGLPFAAllowOfflineRenderers, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_singleBuffered_accel[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFAAllowOfflineRenderers, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered[] = { + NSOpenGLPFAAllowOfflineRenderers, + NSOpenGLPFADoubleBuffer, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_doubleBuffered_accel[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFAAllowOfflineRenderers, + NSOpenGLPFADoubleBuffer, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_offscreen[] = { + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_allow_offline[] = { + NSOpenGLPFAAllowOfflineRenderers, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_accel[] = { + NSOpenGLPFAAccelerated, + 0 +}; + +static const NSOpenGLPixelFormatAttribute kAttribs_offscreen_coreProfile[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + 0 +}; + +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; +} + +already_AddRefed<GLContext> +GLContextProviderCGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + return CreateForWindow(aCompositorWidget->RealWidget(), aForceAccelerated); +} + +already_AddRefed<GLContext> +GLContextProviderCGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + if (!sCGLLibrary.EnsureInitialized()) { + return nullptr; + } + +#ifdef EMULATE_VM + if (aForceAccelerated) { + return nullptr; + } +#endif + + const NSOpenGLPixelFormatAttribute* attribs; + if (sCGLLibrary.UseDoubleBufferedWindows()) { + attribs = aForceAccelerated ? kAttribs_doubleBuffered_accel : kAttribs_doubleBuffered; + } else { + attribs = aForceAccelerated ? kAttribs_singleBuffered_accel : kAttribs_singleBuffered; + } + NSOpenGLContext* context = CreateWithFormat(attribs); + if (!context) { + return nullptr; + } + + // make the context transparent + GLint opaque = 0; + [context setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity]; + + SurfaceCaps caps = SurfaceCaps::ForRGBA(); + ContextProfile profile = ContextProfile::OpenGLCompatibility; + RefPtr<GLContextCGL> glContext = new GLContextCGL(CreateContextFlags::NONE, caps, + context, false, profile); + + if (!glContext->Init()) { + glContext = nullptr; + [context release]; + return nullptr; + } + + return glContext.forget(); +} + +static already_AddRefed<GLContextCGL> +CreateOffscreenFBOContext(CreateContextFlags flags) +{ + if (!sCGLLibrary.EnsureInitialized()) { + return nullptr; + } + + ContextProfile profile; + NSOpenGLContext* context = nullptr; + + if (!(flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE)) { + profile = ContextProfile::OpenGLCore; + context = CreateWithFormat(kAttribs_offscreen_coreProfile); + } + if (!context) { + profile = ContextProfile::OpenGLCompatibility; + + if (flags & CreateContextFlags::ALLOW_OFFLINE_RENDERER) { + if (gfxPrefs::RequireHardwareGL()) + context = CreateWithFormat(kAttribs_singleBuffered); + else + context = CreateWithFormat(kAttribs_offscreen_allow_offline); + + } else { + if (gfxPrefs::RequireHardwareGL()) + context = CreateWithFormat(kAttribs_offscreen_accel); + else + context = CreateWithFormat(kAttribs_offscreen); + } + } + if (!context) { + NS_WARNING("Failed to create NSOpenGLContext."); + return nullptr; + } + + SurfaceCaps dummyCaps = SurfaceCaps::Any(); + RefPtr<GLContextCGL> glContext = new GLContextCGL(flags, dummyCaps, context, true, + profile); + + if (gfxPrefs::GLMultithreaded()) { + CGLEnable(glContext->GetCGLContext(), kCGLCEMPEngine); + } + return glContext.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderCGL::CreateHeadless(CreateContextFlags flags, + nsACString* const out_failureId) +{ + RefPtr<GLContextCGL> gl; + gl = CreateOffscreenFBOContext(flags); + if (!gl) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_FBO"); + return nullptr; + } + + if (!gl->Init()) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_INIT"); + NS_WARNING("Failed during Init."); + return nullptr; + } + + return gl.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderCGL::CreateOffscreen(const IntSize& size, + const SurfaceCaps& minCaps, + CreateContextFlags flags, + nsACString* const out_failureId) +{ + RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId); + if (!gl) { + return nullptr; + } + + if (!gl->InitOffscreen(size, minCaps)) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_CGL_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(CreateContextFlags::NONE, + &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..784a3e29e0 --- /dev/null +++ b/gfx/gl/GLContextProviderEAGL.mm @@ -0,0 +1,281 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "GLContextProvider.h" +#include "GLContextEAGL.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include "gfxPrefs.h" +#include "gfxFailure.h" +#include "prenv.h" +#include "mozilla/Preferences.h" +#include "mozilla/widget/CompositorWidget.h" +#include "GeckoProfiler.h" + +#import <UIKit/UIKit.h> + +namespace mozilla { +namespace gl { + +using namespace mozilla::widget; + +GLContextEAGL::GLContextEAGL(CreateContextFlags flags, const SurfaceCaps& caps, + EAGLContext* context, GLContext* sharedContext, + bool isOffscreen, ContextProfile profile) + : GLContext(flags, caps, sharedContext, isOffscreen) + , mContext(context) + , mBackbufferRB(0) + , mBackbufferFB(0) + , mLayer(nil) +{ + SetProfileVersion(ContextProfile::OpenGLES, + [context API] == kEAGLRenderingAPIOpenGLES3 ? 300 : 200); +} + +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::Init() +{ + if (!InitWithPrefix("gl", true)) + return false; + + return true; +} + +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(bool aForce) +{ + if (!aForce && [EAGLContext currentContext] == mContext) { + return true; + } + + if (mContext) { + if(![EAGLContext setCurrentContext:mContext]) { + return false; + } + } + return true; +} + +bool +GLContextEAGL::IsCurrent() { + return [EAGLContext currentContext] == mContext; +} + +bool +GLContextEAGL::SetupLookupFunction() +{ + return false; +} + +bool +GLContextEAGL::IsDoubleBuffered() const +{ + return true; +} + +bool +GLContextEAGL::SwapBuffers() +{ + PROFILER_LABEL("GLContextEAGL", "SwapBuffers", + js::ProfileEntry::Category::GRAPHICS); + + [mContext presentRenderbuffer:LOCAL_GL_RENDERBUFFER]; + return true; +} + + +already_AddRefed<GLContext> +GLContextProviderEAGL::CreateWrappingExisting(void*, void*) +{ + return nullptr; +} + +static GLContextEAGL* +GetGlobalContextEAGL() +{ + return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext()); +} + +static already_AddRefed<GLContext> +CreateEAGLContext(CreateContextFlags flags, bool aOffscreen, 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; + } + + SurfaceCaps caps = SurfaceCaps::ForRGBA(); + ContextProfile profile = ContextProfile::OpenGLES; + RefPtr<GLContextEAGL> glContext = new GLContextEAGL(flags, caps, context, + sharedContext, + aOffscreen, + profile); + + if (!glContext->Init()) { + glContext = nullptr; + return nullptr; + } + + return glContext.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderEAGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + return CreateForWindow(aCompositorWidget->RealWidget(), aForceAccelerated); +} + +already_AddRefed<GLContext> +GLContextProviderEAGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + RefPtr<GLContext> glContext = CreateEAGLContext(CreateContextFlags::NONE, false, + GetGlobalContextEAGL()); + if (!glContext) { + return nullptr; + } + + if (!GLContextEAGL::Cast(glContext)->AttachToWindow(aWidget)) { + return nullptr; + } + + return glContext.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderEAGL::CreateHeadless(CreateContextFlags flags, + nsACString* const out_failureId) +{ + return CreateEAGLContext(flags, true, GetGlobalContextEAGL()); +} + +already_AddRefed<GLContext> +GLContextProviderEAGL::CreateOffscreen(const mozilla::gfx::IntSize& size, + const SurfaceCaps& caps, + CreateContextFlags flags, + nsACString* const out_failureId) +{ + RefPtr<GLContext> glContext = CreateHeadless(flags, out_failureId); + if (!glContext->InitOffscreen(size, caps)) { + return nullptr; + } + + return glContext.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..ca972e0f3c --- /dev/null +++ b/gfx/gl/GLContextProviderEGL.cpp @@ -0,0 +1,1025 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#if defined(MOZ_WIDGET_GTK) + #include <gdk/gdkx.h> + // we're using default display for now + #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow*)aWidget->GetNativeData(NS_NATIVE_WINDOW))) +#else + #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW)) +#endif + +#ifdef MOZ_WIDGET_ANDROID + #define GET_JAVA_SURFACE(aWidget) (aWidget->GetNativeData(NS_JAVA_SURFACE)) +#endif + +#if defined(XP_UNIX) + #ifdef MOZ_WIDGET_ANDROID + #include <android/native_window.h> + #include <android/native_window_jni.h> + #endif + + #ifdef ANDROID + #include <android/log.h> + #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) + #endif + + #define GLES2_LIB "libGLESv2.so" + #define GLES2_LIB2 "libGLESv2.so.2" + +#elif defined(XP_WIN) + #include "nsIFile.h" + + #define GLES2_LIB "libGLESv2.dll" + + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif + + #include <windows.h> + + // a little helper + class AutoDestroyHWND { + public: + AutoDestroyHWND(HWND aWnd = nullptr) + : mWnd(aWnd) + { + } + + ~AutoDestroyHWND() { + if (mWnd) { + ::DestroyWindow(mWnd); + } + } + + operator HWND() { + return mWnd; + } + + HWND forget() { + HWND w = mWnd; + mWnd = nullptr; + return w; + } + + HWND operator=(HWND aWnd) { + if (mWnd && mWnd != aWnd) { + ::DestroyWindow(mWnd); + } + mWnd = aWnd; + return mWnd; + } + + HWND mWnd; + }; +#else + #error "Platform not recognized" +#endif + +#include "gfxASurface.h" +#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 "mozilla/ArrayUtils.h" +#include "mozilla/Preferences.h" +#include "mozilla/widget/CompositorWidget.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include "nsThreadUtils.h" +#include "ScopedGLHelpers.h" +#include "TextureImageEGL.h" + +using namespace mozilla::gfx; + +namespace mozilla { +namespace gl { + +using namespace mozilla::widget; + +#define ADD_ATTR_2(_array, _k, _v) do { \ + (_array).AppendElement(_k); \ + (_array).AppendElement(_v); \ +} while (0) + +#define ADD_ATTR_1(_array, _k) do { \ + (_array).AppendElement(_k); \ +} while (0) + +static bool +CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget); + +// 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 gTerminationAttribs[] = { + 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 void +DestroySurface(EGLSurface oldSurface) { + if (oldSurface != EGL_NO_SURFACE) { + sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), + EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + sEGLLibrary.fDestroySurface(EGL_DISPLAY(), oldSurface); + } +} + +static EGLSurface +CreateSurfaceForWindow(nsIWidget* widget, const EGLConfig& config) { + EGLSurface newSurface = nullptr; + + MOZ_ASSERT(widget); +#ifdef MOZ_WIDGET_ANDROID + void* javaSurface = GET_JAVA_SURFACE(widget); + if (!javaSurface) { + MOZ_CRASH("GFX: Failed to get Java surface.\n"); + } + JNIEnv* const env = jni::GetEnvForThread(); + ANativeWindow* const nativeWindow = ANativeWindow_fromSurface( + env, reinterpret_cast<jobject>(javaSurface)); + newSurface = sEGLLibrary.fCreateWindowSurface( + sEGLLibrary.fGetDisplay(EGL_DEFAULT_DISPLAY), + config, nativeWindow, 0); + ANativeWindow_release(nativeWindow); +#else + newSurface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, + GET_NATIVE_WINDOW(widget), 0); +#endif + return newSurface; +} + +GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps, + GLContext* shareContext, bool isOffscreen, EGLConfig config, + EGLSurface surface, EGLContext context) + : GLContext(flags, caps, shareContext, isOffscreen) + , mConfig(config) + , mSurface(surface) + , mContext(context) + , mSurfaceOverride(EGL_NO_SURFACE) + , mThebesSurface(nullptr) + , mBound(false) + , mIsPBuffer(false) + , mIsDoubleBuffered(false) + , mCanBindToTexture(false) + , mShareWithEGLImage(false) + , mOwnsContext(true) +{ + // any EGL contexts will always be GLESv2 + SetProfileVersion(ContextProfile::OpenGLES, 200); + +#ifdef DEBUG + printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY()); +#endif +} + +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, EGL_DISPLAY()); +#endif + + sEGLLibrary.fDestroyContext(EGL_DISPLAY(), mContext); + sEGLLibrary.UnsetCachedCurrentContext(); + + mozilla::gl::DestroySurface(mSurface); +} + +bool +GLContextEGL::Init() +{ +#if defined(ANDROID) + // We can't use LoadApitraceLibrary here because the GLContext + // expects its own handle to the GL library + if (!OpenLibrary(APITRACE_LIB)) +#endif + if (!OpenLibrary(GLES2_LIB)) { +#if defined(XP_UNIX) + if (!OpenLibrary(GLES2_LIB2)) { + NS_WARNING("Couldn't load GLES2 LIB."); + return false; + } +#endif + } + + SetupLookupFunction(); + if (!InitWithPrefix("gl", true)) + return false; + + bool current = MakeCurrent(); + if (!current) { + gfx::LogFailure(NS_LITERAL_CSTRING( + "Couldn't get device attachments for device.")); + return false; + } + + static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t"); + mMaxTextureImageSize = INT32_MAX; + + mShareWithEGLImage = sEGLLibrary.HasKHRImageBase() && + sEGLLibrary.HasKHRImageTexture2D() && + IsExtensionSupported(OES_EGL_image); + + return true; +} + +bool +GLContextEGL::BindTexImage() +{ + if (!mSurface) + return false; + + if (mBound && !ReleaseTexImage()) + return false; + + EGLBoolean success = sEGLLibrary.fBindTexImage(EGL_DISPLAY(), + (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 = sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(), + (EGLSurface)mSurface, + LOCAL_EGL_BACK_BUFFER); + if (success == LOCAL_EGL_FALSE) + return false; + + mBound = false; + return true; +} + +void +GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) { + if (Screen()) { + /* Blit `draw` to `read` if we need to, before we potentially juggle + * `read` around. If we don't, we might attach a different `read`, + * and *then* hit AssureBlitted, which will blit a dirty `draw` onto + * the wrong `read`! + */ + Screen()->AssureBlitted(); + } + + mSurfaceOverride = surf; + DebugOnly<bool> ok = MakeCurrent(true); + MOZ_ASSERT(ok); +} + +bool +GLContextEGL::MakeCurrentImpl(bool aForce) { + bool succeeded = true; + + // Assume that EGL has the same problem as WGL does, + // where MakeCurrent with an already-current context is + // still expensive. + bool hasDifferentContext = false; + if (sEGLLibrary.CachedCurrentContext() != mContext) { + // even if the cached context doesn't match the current one + // might still + if (sEGLLibrary.fGetCurrentContext() != mContext) { + hasDifferentContext = true; + } else { + sEGLLibrary.SetCachedCurrentContext(mContext); + } + } + + if (aForce || hasDifferentContext) { + EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE + ? mSurfaceOverride + : mSurface; + if (surface == EGL_NO_SURFACE) { + return false; + } + succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), + surface, surface, + mContext); + if (!succeeded) { + int eglError = sEGLLibrary.fGetError(); + if (eglError == LOCAL_EGL_CONTEXT_LOST) { + mContextLost = true; + NS_WARNING("EGL context has been lost."); + } else { + NS_WARNING("Failed to make GL context current!"); +#ifdef DEBUG + printf_stderr("EGL Error: 0x%04x\n", eglError); +#endif + } + } else { + sEGLLibrary.SetCachedCurrentContext(mContext); + } + } else { + MOZ_ASSERT(sEGLLibrary.CachedCurrentContextMatches()); + } + + return succeeded; +} + +bool +GLContextEGL::IsCurrent() { + return sEGLLibrary.fGetCurrentContext() == mContext; +} + +bool +GLContextEGL::RenewSurface(nsIWidget* 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(); + mSurface = mozilla::gl::CreateSurfaceForWindow(aWidget, mConfig); + if (!mSurface) { + return false; + } + return MakeCurrent(true); +} + +void +GLContextEGL::ReleaseSurface() { + if (mOwnsContext) { + mozilla::gl::DestroySurface(mSurface); + } + if (mSurface == mSurfaceOverride) { + mSurfaceOverride = EGL_NO_SURFACE; + } + mSurface = EGL_NO_SURFACE; +} + +bool +GLContextEGL::SetupLookupFunction() +{ + mLookupFunc = (PlatformLookupFunction)sEGLLibrary.mSymbols.fGetProcAddress; + return true; +} + +bool +GLContextEGL::SwapBuffers() +{ + EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE + ? mSurfaceOverride + : mSurface; + if (surface) { + return sEGLLibrary.fSwapBuffers(EGL_DISPLAY(), surface); + } else { + return false; + } +} + +// hold a reference to the given surface +// for the lifetime of this context. +void +GLContextEGL::HoldSurface(gfxASurface* aSurf) { + mThebesSurface = aSurf; +} + +/* static */ EGLSurface +GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget) +{ + nsCString discardFailureId; + if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) { + MOZ_CRASH("GFX: Failed to load EGL library!\n"); + return nullptr; + } + + EGLConfig config; + if (!CreateConfig(&config, aWidget)) { + MOZ_CRASH("GFX: Failed to create EGLConfig!\n"); + return nullptr; + } + + EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config); + if (!surface) { + MOZ_CRASH("GFX: Failed to create EGLSurface for window!\n"); + return nullptr; + } + return surface; +} + +/* static */ void +GLContextEGL::DestroySurface(EGLSurface aSurface) +{ + if (aSurface != EGL_NO_SURFACE) { + sEGLLibrary.fDestroySurface(EGL_DISPLAY(), aSurface); + } +} + +already_AddRefed<GLContextEGL> +GLContextEGL::CreateGLContext(CreateContextFlags flags, + const SurfaceCaps& caps, + GLContextEGL* shareContext, + bool isOffscreen, + EGLConfig config, + EGLSurface surface, + nsACString* const out_failureId) +{ + if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_ES"); + NS_WARNING("Failed to bind API to GLES!"); + return nullptr; + } + + EGLContext eglShareContext = shareContext ? shareContext->mContext + : EGL_NO_CONTEXT; + + nsTArray<EGLint> contextAttribs; + + contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_CLIENT_VERSION); + if (flags & CreateContextFlags::PREFER_ES3) + contextAttribs.AppendElement(3); + else + contextAttribs.AppendElement(2); + + if (sEGLLibrary.HasRobustness()) { +// contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT); +// contextAttribs.AppendElement(LOCAL_EGL_TRUE); + } + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(gTerminationAttribs); i++) { + contextAttribs.AppendElement(gTerminationAttribs[i]); + } + + EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), + config, + eglShareContext, + contextAttribs.Elements()); + if (!context && shareContext) { + shareContext = nullptr; + context = sEGLLibrary.fCreateContext(EGL_DISPLAY(), config, EGL_NO_CONTEXT, + contextAttribs.Elements()); + } + if (!context) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_CREATE"); + NS_WARNING("Failed to create EGLContext!"); + return nullptr; + } + + RefPtr<GLContextEGL> glContext = new GLContextEGL(flags, caps, shareContext, + isOffscreen, config, surface, + context); + + if (!glContext->Init()) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_INIT"); + return nullptr; + } + + return glContext.forget(); +} + +EGLSurface +GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(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 (size_t i = 0; i < MOZ_ARRAY_LENGTH(gTerminationAttribs); i++) { + pbattrs.AppendElement(gTerminationAttribs[i]); + } + + surface = sEGLLibrary.fCreatePbufferSurface(EGL_DISPLAY(), 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; +} + +static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = { + LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT, + LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + // Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856) + LOCAL_EGL_RED_SIZE, 8, + LOCAL_EGL_GREEN_SIZE, 8, + LOCAL_EGL_BLUE_SIZE, 8, + LOCAL_EGL_ALPHA_SIZE, 0, + EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS +}; + +static const EGLint kEGLConfigAttribsRGB16[] = { + LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT, + LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + LOCAL_EGL_RED_SIZE, 5, + LOCAL_EGL_GREEN_SIZE, 6, + LOCAL_EGL_BLUE_SIZE, 5, + LOCAL_EGL_ALPHA_SIZE, 0, + EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS +}; + +static const EGLint kEGLConfigAttribsRGB24[] = { + LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT, + LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + LOCAL_EGL_RED_SIZE, 8, + LOCAL_EGL_GREEN_SIZE, 8, + LOCAL_EGL_BLUE_SIZE, 8, + LOCAL_EGL_ALPHA_SIZE, 0, + EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS +}; + +static const EGLint kEGLConfigAttribsRGBA32[] = { + LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT, + LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + LOCAL_EGL_RED_SIZE, 8, + LOCAL_EGL_GREEN_SIZE, 8, + LOCAL_EGL_BLUE_SIZE, 8, + LOCAL_EGL_ALPHA_SIZE, 8, + EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS +}; + +static bool +CreateConfig(EGLConfig* aConfig, int32_t depth, nsIWidget* aWidget) +{ + EGLConfig configs[64]; + const EGLint* attribs; + EGLint ncfg = ArrayLength(configs); + + switch (depth) { + case 16: + attribs = kEGLConfigAttribsRGB16; + break; + case 24: + attribs = kEGLConfigAttribsRGB24; + break; + case 32: + attribs = kEGLConfigAttribsRGBA32; + break; + default: + NS_ERROR("Unknown pixel depth"); + return false; + } + + if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs, + configs, ncfg, &ncfg) || + ncfg < 1) { + return false; + } + + for (int j = 0; j < ncfg; ++j) { + EGLConfig config = configs[j]; + EGLint r, g, b, a; + if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config, + LOCAL_EGL_RED_SIZE, &r) && + sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config, + LOCAL_EGL_GREEN_SIZE, &g) && + sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config, + LOCAL_EGL_BLUE_SIZE, &b) && + sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config, + LOCAL_EGL_ALPHA_SIZE, &a) && + ((depth == 16 && r == 5 && g == 6 && b == 5) || + (depth == 24 && r == 8 && g == 8 && b == 8) || + (depth == 32 && r == 8 && g == 8 && b == 8 && a == 8))) + { + *aConfig = config; + 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 +CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget) +{ + int32_t depth = gfxPlatform::GetPlatform()->GetScreenDepth(); + if (!CreateConfig(aConfig, depth, aWidget)) { +#ifdef MOZ_WIDGET_ANDROID + // Bug 736005 + // Android doesn't always support 16 bit so also try 24 bit + if (depth == 16) { + return CreateConfig(aConfig, 24, aWidget); + } + // Bug 970096 + // Some devices that have 24 bit screens only support 16 bit OpenGL? + if (depth == 24) { + return CreateConfig(aConfig, 16, aWidget); + } +#endif + return false; + } else { + return true; + } +} + +already_AddRefed<GLContext> +GLContextProviderEGL::CreateWrappingExisting(void* aContext, void* aSurface) +{ + nsCString discardFailureId; + if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) { + MOZ_CRASH("GFX: Failed to load EGL library 2!\n"); + return nullptr; + } + + if (!aContext || !aSurface) + return nullptr; + + SurfaceCaps caps = SurfaceCaps::Any(); + EGLConfig config = EGL_NO_CONFIG; + RefPtr<GLContextEGL> gl = new GLContextEGL(CreateContextFlags::NONE, caps, nullptr, + false, config, (EGLSurface)aSurface, + (EGLContext)aContext); + gl->SetIsDoubleBuffered(true); + gl->mOwnsContext = false; + + return gl.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderEGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + return CreateForWindow(aCompositorWidget->RealWidget(), aForceAccelerated); +} + +already_AddRefed<GLContext> +GLContextProviderEGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + nsCString discardFailureId; + if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) { + MOZ_CRASH("GFX: Failed to load EGL library 3!\n"); + return nullptr; + } + + bool doubleBuffered = true; + + EGLConfig config; + if (!CreateConfig(&config, aWidget)) { + MOZ_CRASH("GFX: Failed to create EGLConfig!\n"); + return nullptr; + } + + EGLSurface surface = mozilla::gl::CreateSurfaceForWindow(aWidget, config); + if (!surface) { + MOZ_CRASH("GFX: Failed to create EGLSurface!\n"); + return nullptr; + } + + SurfaceCaps caps = SurfaceCaps::Any(); + RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(CreateContextFlags::NONE, + caps, nullptr, false, config, + surface, &discardFailureId); + if (!gl) { + MOZ_CRASH("GFX: Failed to create EGLContext!\n"); + mozilla::gl::DestroySurface(surface); + return nullptr; + } + + gl->MakeCurrent(); + gl->SetIsDoubleBuffered(doubleBuffered); + + return gl.forget(); +} + +#if defined(ANDROID) +EGLSurface +GLContextProviderEGL::CreateEGLSurface(void* aWindow) +{ + nsCString discardFailureId; + if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) { + MOZ_CRASH("GFX: Failed to load EGL library 4!\n"); + } + + EGLConfig config; + if (!CreateConfig(&config, static_cast<nsIWidget*>(aWindow))) { + MOZ_CRASH("GFX: Failed to create EGLConfig 2!\n"); + } + + MOZ_ASSERT(aWindow); + + EGLSurface surface = sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, aWindow, + 0); + if (surface == EGL_NO_SURFACE) { + MOZ_CRASH("GFX: Failed to create EGLSurface 2!\n"); + } + + return surface; +} + +void +GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface) +{ + nsCString discardFailureId; + if (!sEGLLibrary.EnsureInitialized(false, &discardFailureId)) { + MOZ_CRASH("GFX: Failed to load EGL library 5!\n"); + } + + sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface); +} +#endif // defined(ANDROID) + +static void +FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16, + bool es3, nsTArray<EGLint>* out) +{ + out->AppendElement(LOCAL_EGL_SURFACE_TYPE); + out->AppendElement(LOCAL_EGL_PBUFFER_BIT); + + 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); + if (bpp16) { + out->AppendElement(alpha ? 4 : 5); + } else { + out->AppendElement(8); + } + + out->AppendElement(LOCAL_EGL_GREEN_SIZE); + if (bpp16) { + out->AppendElement(alpha ? 4 : 6); + } else { + out->AppendElement(8); + } + + out->AppendElement(LOCAL_EGL_BLUE_SIZE); + if (bpp16) { + out->AppendElement(alpha ? 4 : 5); + } else { + out->AppendElement(8); + } + + out->AppendElement(LOCAL_EGL_ALPHA_SIZE); + if (alpha) { + out->AppendElement(bpp16 ? 4 : 8); + } else { + out->AppendElement(0); + } + + out->AppendElement(LOCAL_EGL_DEPTH_SIZE); + out->AppendElement(depth ? 16 : 0); + + out->AppendElement(LOCAL_EGL_STENCIL_SIZE); + out->AppendElement(stencil ? 8 : 0); + + // EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS + out->AppendElement(LOCAL_EGL_NONE); + out->AppendElement(0); + + out->AppendElement(0); + out->AppendElement(0); +} + +static GLint +GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib) +{ + EGLint bits = 0; + egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits); + MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS); + + return bits; +} + +static EGLConfig +ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& minCaps, + SurfaceCaps* const out_configCaps) +{ + nsTArray<EGLint> configAttribList; + FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16, + bool(flags & CreateContextFlags::PREFER_ES3), &configAttribList); + + const EGLint* configAttribs = configAttribList.Elements(); + + // We're guaranteed to get at least minCaps, and 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(egl->Display(), configAttribs, configs, kMaxConfigs, + &foundConfigs) + || foundConfigs == 0) + { + return EGL_NO_CONFIG; + } + + EGLConfig config = configs[0]; + + *out_configCaps = minCaps; // Pick up any preserve, etc. + out_configCaps->color = true; + out_configCaps->alpha = bool(GetAttrib(egl, config, LOCAL_EGL_ALPHA_SIZE)); + out_configCaps->depth = bool(GetAttrib(egl, config, LOCAL_EGL_DEPTH_SIZE)); + out_configCaps->stencil = bool(GetAttrib(egl, config, LOCAL_EGL_STENCIL_SIZE)); + out_configCaps->bpp16 = (GetAttrib(egl, config, LOCAL_EGL_RED_SIZE) < 8); + + return config; +} + +/*static*/ already_AddRefed<GLContextEGL> +GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags, + const mozilla::gfx::IntSize& size, + const SurfaceCaps& minCaps, + nsACString* const out_failureId) +{ + bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE); + if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, out_failureId)) { + return nullptr; + } + + SurfaceCaps configCaps; + EGLConfig config = ChooseConfig(&sEGLLibrary, flags, minCaps, &configCaps); + if (config == EGL_NO_CONFIG) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_NO_CONFIG"); + NS_WARNING("Failed to find a compatible config."); + return nullptr; + } + + if (GLContext::ShouldSpew()) { + sEGLLibrary.DumpEGLConfig(config); + } + + mozilla::gfx::IntSize pbSize(size); + EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config, + LOCAL_EGL_NONE, + pbSize); + if (!surface) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT"); + NS_WARNING("Failed to create PBuffer for context!"); + return nullptr; + } + + RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(flags, configCaps, nullptr, + true, config, surface, + out_failureId); + if (!gl) { + NS_WARNING("Failed to create GLContext from PBuffer"); + sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface); + return nullptr; + } + + return gl.forget(); +} + +/*static*/ already_AddRefed<GLContext> +GLContextProviderEGL::CreateHeadless(CreateContextFlags flags, + nsACString* const out_failureId) +{ + mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16); + SurfaceCaps dummyCaps = SurfaceCaps::Any(); + return GLContextEGL::CreateEGLPBufferOffscreenContext(flags, dummySize, dummyCaps, + out_failureId); +} + +// Under EGL, on Android, pbuffers are supported fine, though +// often without the ability to texture from them directly. +/*static*/ already_AddRefed<GLContext> +GLContextProviderEGL::CreateOffscreen(const mozilla::gfx::IntSize& size, + const SurfaceCaps& minCaps, + CreateContextFlags flags, + nsACString* const out_failureId) +{ + bool forceEnableHardware = bool(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE); + if (!sEGLLibrary.EnsureInitialized(forceEnableHardware, out_failureId)) { // Needed for IsANGLE(). + return nullptr; + } + + bool canOffscreenUseHeadless = true; + if (sEGLLibrary.IsANGLE()) { + // ANGLE needs to use PBuffers. + canOffscreenUseHeadless = false; + } + + RefPtr<GLContext> gl; + SurfaceCaps minOffscreenCaps = minCaps; + + if (canOffscreenUseHeadless) { + gl = CreateHeadless(flags, out_failureId); + if (!gl) { + return nullptr; + } + } else { + SurfaceCaps minBackbufferCaps = minOffscreenCaps; + if (minOffscreenCaps.antialias) { + minBackbufferCaps.antialias = false; + minBackbufferCaps.depth = false; + minBackbufferCaps.stencil = false; + } + + gl = GLContextEGL::CreateEGLPBufferOffscreenContext(flags, size, + minBackbufferCaps, + out_failureId); + if (!gl) + return nullptr; + + // Pull the actual resulting caps to ensure that our offscreen matches our + // backbuffer. + minOffscreenCaps.alpha = gl->Caps().alpha; + if (!minOffscreenCaps.antialias) { + // Only update these if we don't have AA. If we do have AA, we ignore + // backbuffer depth/stencil. + minOffscreenCaps.depth = gl->Caps().depth; + minOffscreenCaps.stencil = gl->Caps().stencil; + } + } + + // Init the offscreen with the updated offscreen caps. + if (!gl->InitOffscreen(size, minOffscreenCaps)) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_OFFSCREEN"); + return nullptr; + } + + return gl.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() +{ +} + +} /* 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..9a1157f330 --- /dev/null +++ b/gfx/gl/GLContextProviderGLX.cpp @@ -0,0 +1,1421 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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/. */ + +#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/widget/CompositorWidget.h" +#include "mozilla/widget/X11CompositorWidget.h" +#include "mozilla/Unused.h" + +#include "prenv.h" +#include "GLContextProvider.h" +#include "GLLibraryLoader.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include "GLXLibrary.h" +#include "gfxXlibSurface.h" +#include "gfxContext.h" +#include "gfxEnv.h" +#include "gfxPlatform.h" +#include "GLContextGLX.h" +#include "gfxUtils.h" +#include "gfx2DGlue.h" +#include "GLScreenBuffer.h" +#include "gfxPrefs.h" + +#include "gfxCrashReporterUtils.h" + +#ifdef MOZ_WIDGET_GTK +#include "gfxPlatformGtk.h" +#endif + +namespace mozilla { +namespace gl { + +using namespace mozilla::gfx; +using namespace mozilla::widget; + +GLXLibrary sGLXLibrary; + +// Check that we have at least version aMajor.aMinor . +bool +GLXLibrary::GLXVersionCheck(int aMajor, int aMinor) +{ + return aMajor < mGLXMajorVersion || + (aMajor == mGLXMajorVersion && aMinor <= mGLXMinorVersion); +} + +static inline bool +HasExtension(const char* aExtensions, const char* aRequiredExtension) +{ + return GLContext::ListHasExtension( + reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension); +} + +bool +GLXLibrary::EnsureInitialized() +{ + if (mInitialized) { + return true; + } + + // Don't repeatedly try to initialize. + if (mTriedInitializing) { + return false; + } + mTriedInitializing = true; + + // Force enabling s3 texture compression. (Bug 774134) + PR_SetEnv("force_s3tc_enable=true"); + + if (!mOGLLibrary) { + const char* libGLfilename = nullptr; + bool forceFeatureReport = false; + + // 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 +#ifdef __OpenBSD__ + libGLfilename = "libGL.so"; +#else + libGLfilename = "libGL.so.1"; +#endif + + ScopedGfxFeatureReporter reporter(libGLfilename, forceFeatureReport); + mOGLLibrary = PR_LoadLibrary(libGLfilename); + if (!mOGLLibrary) { + NS_WARNING("Couldn't load OpenGL shared library."); + return false; + } + reporter.SetSuccessful(); + } + + if (gfxEnv::GlxDebug()) { + mDebug = true; + } + + GLLibraryLoader::SymLoadStruct symbols[] = { + /* functions that were in GLX 1.0 */ + { (PRFuncPtr*) &xDestroyContextInternal, { "glXDestroyContext", nullptr } }, + { (PRFuncPtr*) &xMakeCurrentInternal, { "glXMakeCurrent", nullptr } }, + { (PRFuncPtr*) &xSwapBuffersInternal, { "glXSwapBuffers", nullptr } }, + { (PRFuncPtr*) &xQueryVersionInternal, { "glXQueryVersion", nullptr } }, + { (PRFuncPtr*) &xGetCurrentContextInternal, { "glXGetCurrentContext", nullptr } }, + { (PRFuncPtr*) &xWaitGLInternal, { "glXWaitGL", nullptr } }, + { (PRFuncPtr*) &xWaitXInternal, { "glXWaitX", nullptr } }, + /* functions introduced in GLX 1.1 */ + { (PRFuncPtr*) &xQueryExtensionsStringInternal, { "glXQueryExtensionsString", nullptr } }, + { (PRFuncPtr*) &xGetClientStringInternal, { "glXGetClientString", nullptr } }, + { (PRFuncPtr*) &xQueryServerStringInternal, { "glXQueryServerString", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols13[] = { + /* functions introduced in GLX 1.3 */ + { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfig", nullptr } }, + { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttrib", nullptr } }, + // WARNING: xGetFBConfigs not set in symbols13_ext + { (PRFuncPtr*) &xGetFBConfigsInternal, { "glXGetFBConfigs", nullptr } }, + // WARNING: symbols13_ext sets xCreateGLXPixmapWithConfig instead + { (PRFuncPtr*) &xCreatePixmapInternal, { "glXCreatePixmap", nullptr } }, + { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyPixmap", nullptr } }, + { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateNewContext", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols13_ext[] = { + /* extension equivalents for functions introduced in GLX 1.3 */ + // GLX_SGIX_fbconfig extension + { (PRFuncPtr*) &xChooseFBConfigInternal, { "glXChooseFBConfigSGIX", nullptr } }, + { (PRFuncPtr*) &xGetFBConfigAttribInternal, { "glXGetFBConfigAttribSGIX", nullptr } }, + // WARNING: no xGetFBConfigs equivalent in extensions + // WARNING: different from symbols13: + { (PRFuncPtr*) &xCreateGLXPixmapWithConfigInternal, { "glXCreateGLXPixmapWithConfigSGIX", nullptr } }, + { (PRFuncPtr*) &xDestroyPixmapInternal, { "glXDestroyGLXPixmap", nullptr } }, // not from ext + { (PRFuncPtr*) &xCreateNewContextInternal, { "glXCreateContextWithConfigSGIX", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols14[] = { + /* functions introduced in GLX 1.4 */ + { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddress", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols14_ext[] = { + /* extension equivalents for functions introduced in GLX 1.4 */ + // GLX_ARB_get_proc_address extension + { (PRFuncPtr*) &xGetProcAddressInternal, { "glXGetProcAddressARB", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols_texturefrompixmap[] = { + { (PRFuncPtr*) &xBindTexImageInternal, { "glXBindTexImageEXT", nullptr } }, + { (PRFuncPtr*) &xReleaseTexImageInternal, { "glXReleaseTexImageEXT", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols_createcontext[] = { + { (PRFuncPtr*) &xCreateContextAttribsInternal, { "glXCreateContextAttribsARB", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols_videosync[] = { + { (PRFuncPtr*) &xGetVideoSyncInternal, { "glXGetVideoSyncSGI", nullptr } }, + { (PRFuncPtr*) &xWaitVideoSyncInternal, { "glXWaitVideoSyncSGI", nullptr } }, + { nullptr, { nullptr } } + }; + + GLLibraryLoader::SymLoadStruct symbols_swapcontrol[] = { + { (PRFuncPtr*) &xSwapIntervalInternal, { "glXSwapIntervalEXT", nullptr } }, + { nullptr, { nullptr } } + }; + + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &symbols[0])) { + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); + return false; + } + + Display* display = DefaultXDisplay(); + int screen = DefaultScreen(display); + + if (!xQueryVersion(display, &mGLXMajorVersion, &mGLXMinorVersion)) { + mGLXMajorVersion = 0; + mGLXMinorVersion = 0; + return false; + } + + if (!GLXVersionCheck(1, 1)) + // Not possible to query for extensions. + return false; + + const char* clientVendor = xGetClientString(display, LOCAL_GLX_VENDOR); + const char* serverVendor = xQueryServerString(display, screen, LOCAL_GLX_VENDOR); + const char* extensionsStr = xQueryExtensionsString(display, screen); + + GLLibraryLoader::SymLoadStruct* sym13; + if (!GLXVersionCheck(1, 3)) { + // Even if we don't have 1.3, we might have equivalent extensions + // (as on the Intel X server). + if (!HasExtension(extensionsStr, "GLX_SGIX_fbconfig")) { + return false; + } + sym13 = symbols13_ext; + } else { + sym13 = symbols13; + } + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym13)) { + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); + return false; + } + + GLLibraryLoader::SymLoadStruct* sym14; + if (!GLXVersionCheck(1, 4)) { + // Even if we don't have 1.4, we might have equivalent extensions + // (as on the Intel X server). + if (!HasExtension(extensionsStr, "GLX_ARB_get_proc_address")) { + return false; + } + sym14 = symbols14_ext; + } else { + sym14 = symbols14; + } + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, sym14)) { + NS_WARNING("Couldn't find required entry point in OpenGL shared library"); + return false; + } + + if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") && + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_texturefrompixmap, + (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress)) + { + mUseTextureFromPixmap = gfxPrefs::UseGLXTextureFromPixmap(); + } else { + mUseTextureFromPixmap = false; + NS_WARNING("Texture from pixmap disabled"); + } + + if (HasExtension(extensionsStr, "GLX_ARB_create_context") && + HasExtension(extensionsStr, "GLX_ARB_create_context_profile") && + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_createcontext, + (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress)) + { + mHasCreateContextAttribs = true; + } + + if (HasExtension(extensionsStr, "GLX_ARB_create_context_robustness")) + { + mHasRobustness = true; + } + + if (HasExtension(extensionsStr, "GLX_SGI_video_sync") && + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_videosync, + (GLLibraryLoader::PlatformLookupFunction)&xGetProcAddress)) + { + mHasVideoSync = true; + } + + if (!(HasExtension(extensionsStr, "GLX_EXT_swap_control") && + GLLibraryLoader::LoadSymbols(mOGLLibrary, symbols_swapcontrol))) + { + NS_WARNING("GLX_swap_control unsupported, ASAP mode may still block on buffer swaps."); + } + + mIsATI = serverVendor && DoesStringMatch(serverVendor, "ATI"); + mIsNVIDIA = serverVendor && DoesStringMatch(serverVendor, "NVIDIA Corporation"); + mClientIsMesa = clientVendor && DoesStringMatch(clientVendor, "Mesa"); + + mInitialized = true; + + return true; +} + +bool +GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface) +{ + if (!EnsureInitialized()) { + return false; + } + + if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) { + return false; + } + + return true; +} + +bool +GLXLibrary::SupportsVideoSync() +{ + if (!EnsureInitialized()) { + return false; + } + + return mHasVideoSync; +} + +GLXPixmap +GLXLibrary::CreatePixmap(gfxASurface* aSurface) +{ + if (!SupportsTextureFromPixmap(aSurface)) { + return X11None; + } + + gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface); + const XRenderPictFormat* format = xs->XRenderFormat(); + if (!format || format->type != PictTypeDirect) { + return X11None; + } + const XRenderDirectFormat& direct = format->direct; + int alphaSize = FloorLog2(direct.alphaMask + 1); + NS_ASSERTION((1 << alphaSize) - 1 == direct.alphaMask, + "Unexpected render format with non-adjacent alpha bits"); + + int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False, + LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, + LOCAL_GLX_ALPHA_SIZE, alphaSize, + (alphaSize ? LOCAL_GLX_BIND_TO_TEXTURE_RGBA_EXT + : LOCAL_GLX_BIND_TO_TEXTURE_RGB_EXT), True, + LOCAL_GLX_RENDER_TYPE, LOCAL_GLX_RGBA_BIT, + X11None }; + + int numConfigs = 0; + Display* display = xs->XDisplay(); + int xscreen = DefaultScreen(display); + + ScopedXFree<GLXFBConfig> cfgs(xChooseFBConfig(display, + xscreen, + attribs, + &numConfigs)); + + // Find an fbconfig that matches the pixel format used on the Pixmap. + int matchIndex = -1; + unsigned long redMask = + static_cast<unsigned long>(direct.redMask) << direct.red; + unsigned long greenMask = + static_cast<unsigned long>(direct.greenMask) << direct.green; + unsigned long blueMask = + static_cast<unsigned long>(direct.blueMask) << direct.blue; + // This is true if the Pixmap has bits for alpha or unused bits. + bool haveNonColorBits = + ~(redMask | greenMask | blueMask) != -1UL << format->depth; + + for (int i = 0; i < numConfigs; i++) { + int id = X11None; + sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &id); + Visual* visual; + int depth; + FindVisualAndDepth(display, id, &visual, &depth); + if (!visual || + visual->c_class != TrueColor || + visual->red_mask != redMask || + visual->green_mask != greenMask || + visual->blue_mask != blueMask ) { + continue; + } + + // Historically Xlib Visuals did not try to represent an alpha channel + // and there was no means to use an alpha channel on a Pixmap. The + // Xlib Visual from the fbconfig was not intended to have any + // information about alpha bits. + // + // Since then, RENDER has added formats for 32 bit depth Pixmaps. + // Some of these formats have bits for alpha and some have unused + // bits. + // + // Then the Composite extension added a 32 bit depth Visual intended + // for Windows with an alpha channel, so bits not in the visual color + // masks were expected to be treated as alpha bits. + // + // Usually GLX counts only color bits in the Visual depth, but the + // depth of Composite's ARGB Visual includes alpha bits. However, + // bits not in the color masks are not necessarily alpha bits because + // sometimes (NVIDIA) 32 bit Visuals are added for fbconfigs with 32 + // bit BUFFER_SIZE but zero alpha bits and 24 color bits (NVIDIA + // again). + // + // This checks that the depth matches in one of the two ways. + // NVIDIA now forces format->depth == depth so only the first way + // is checked for NVIDIA + if (depth != format->depth && + (mIsNVIDIA || depth != format->depth - alphaSize) ) { + continue; + } + + // If all bits of the Pixmap are color bits and the Pixmap depth + // matches the depth of the fbconfig visual, then we can assume that + // the driver will do whatever is necessary to ensure that any + // GLXPixmap alpha bits are treated as set. We can skip the + // ALPHA_SIZE check in this situation. We need to skip this check for + // situations (ATI) where there are no fbconfigs without alpha bits. + // + // glXChooseFBConfig should prefer configs with smaller + // LOCAL_GLX_BUFFER_SIZE, so we should still get zero alpha bits if + // available, except perhaps with NVIDIA drivers where buffer size is + // not the specified sum of the component sizes. + if (haveNonColorBits) { + // There are bits in the Pixmap format that haven't been matched + // against the fbconfig visual. These bits could either represent + // alpha or be unused, so just check that the number of alpha bits + // matches. + int size = 0; + sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], + LOCAL_GLX_ALPHA_SIZE, &size); + if (size != alphaSize) { + continue; + } + } + + matchIndex = i; + break; + } + if (matchIndex == -1) { + // GLX can't handle A8 surfaces, so this is not really unexpected. The + // caller should deal with this situation. + NS_WARNING_ASSERTION( + format->depth == 8, + "[GLX] Couldn't find a FBConfig matching Pixmap format"); + return X11None; + } + + int pixmapAttribs[] = { LOCAL_GLX_TEXTURE_TARGET_EXT, LOCAL_GLX_TEXTURE_2D_EXT, + LOCAL_GLX_TEXTURE_FORMAT_EXT, + (alphaSize ? LOCAL_GLX_TEXTURE_FORMAT_RGBA_EXT + : LOCAL_GLX_TEXTURE_FORMAT_RGB_EXT), + X11None}; + + GLXPixmap glxpixmap = xCreatePixmap(display, + cfgs[matchIndex], + xs->XDrawable(), + pixmapAttribs); + + return glxpixmap; +} + +void +GLXLibrary::DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap) +{ + if (!mUseTextureFromPixmap) { + return; + } + + xDestroyPixmap(aDisplay, aPixmap); +} + +void +GLXLibrary::BindTexImage(Display* aDisplay, GLXPixmap aPixmap) +{ + if (!mUseTextureFromPixmap) { + return; + } + + // Make sure all X drawing to the surface has finished before binding to a texture. + if (mClientIsMesa) { + // Using XSync instead of Mesa's glXWaitX, because its glxWaitX is a + // noop when direct rendering unless the current drawable is a + // single-buffer window. + FinishX(aDisplay); + } else { + xWaitX(); + } + xBindTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT, nullptr); +} + +void +GLXLibrary::ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap) +{ + if (!mUseTextureFromPixmap) { + return; + } + + xReleaseTexImage(aDisplay, aPixmap, LOCAL_GLX_FRONT_LEFT_EXT); +} + +void +GLXLibrary::UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap) +{ + // NVIDIA drivers don't require a rebind of the pixmap in order + // to display an updated image, and it's faster not to do it. + if (mIsNVIDIA) { + xWaitX(); + return; + } + + ReleaseTexImage(aDisplay, aPixmap); + BindTexImage(aDisplay, aPixmap); +} + +#ifdef DEBUG + +static int (*sOldErrorHandler)(Display*, XErrorEvent*); +ScopedXErrorHandler::ErrorEvent sErrorEvent; +static int GLXErrorHandler(Display* display, XErrorEvent* ev) +{ + if (!sErrorEvent.mError.error_code) { + sErrorEvent.mError = *ev; + } + return 0; +} + +void +GLXLibrary::BeforeGLXCall() +{ + if (mDebug) { + sOldErrorHandler = XSetErrorHandler(GLXErrorHandler); + } +} + +void +GLXLibrary::AfterGLXCall() +{ + if (mDebug) { + FinishX(DefaultXDisplay()); + if (sErrorEvent.mError.error_code) { + char buffer[2048]; + XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer, sizeof(buffer)); + printf_stderr("X ERROR: %s (%i) - Request: %i.%i, Serial: %lu", + buffer, + sErrorEvent.mError.error_code, + sErrorEvent.mError.request_code, + sErrorEvent.mError.minor_code, + sErrorEvent.mError.serial); + NS_ABORT(); + } + XSetErrorHandler(sOldErrorHandler); + } +} + +#define BEFORE_GLX_CALL do { \ + sGLXLibrary.BeforeGLXCall(); \ +} while (0) + +#define AFTER_GLX_CALL do { \ + sGLXLibrary.AfterGLXCall(); \ +} while (0) + +#else + +#define BEFORE_GLX_CALL do { } while(0) +#define AFTER_GLX_CALL do { } while(0) + +#endif + +void +GLXLibrary::xDestroyContext(Display* display, GLXContext context) +{ + BEFORE_GLX_CALL; + xDestroyContextInternal(display, context); + AFTER_GLX_CALL; +} + +Bool +GLXLibrary::xMakeCurrent(Display* display, + GLXDrawable drawable, + GLXContext context) +{ + BEFORE_GLX_CALL; + Bool result = xMakeCurrentInternal(display, drawable, context); + AFTER_GLX_CALL; + return result; +} + +GLXContext +GLXLibrary::xGetCurrentContext() +{ + BEFORE_GLX_CALL; + GLXContext result = xGetCurrentContextInternal(); + AFTER_GLX_CALL; + return result; +} + +/* static */ void* +GLXLibrary::xGetProcAddress(const char* procName) +{ + BEFORE_GLX_CALL; + void* result = sGLXLibrary.xGetProcAddressInternal(procName); + AFTER_GLX_CALL; + return result; +} + +GLXFBConfig* +GLXLibrary::xChooseFBConfig(Display* display, + int screen, + const int* attrib_list, + int* nelements) +{ + BEFORE_GLX_CALL; + GLXFBConfig* result = xChooseFBConfigInternal(display, screen, attrib_list, nelements); + AFTER_GLX_CALL; + return result; +} + +GLXFBConfig* +GLXLibrary::xGetFBConfigs(Display* display, + int screen, + int* nelements) +{ + BEFORE_GLX_CALL; + GLXFBConfig* result = xGetFBConfigsInternal(display, screen, nelements); + AFTER_GLX_CALL; + return result; +} + +GLXContext +GLXLibrary::xCreateNewContext(Display* display, + GLXFBConfig config, + int render_type, + GLXContext share_list, + Bool direct) +{ + BEFORE_GLX_CALL; + GLXContext result = xCreateNewContextInternal(display, config, + render_type, + share_list, direct); + AFTER_GLX_CALL; + return result; +} + +int +GLXLibrary::xGetFBConfigAttrib(Display* display, + GLXFBConfig config, + int attribute, + int* value) +{ + BEFORE_GLX_CALL; + int result = xGetFBConfigAttribInternal(display, config, + attribute, value); + AFTER_GLX_CALL; + return result; +} + +void +GLXLibrary::xSwapBuffers(Display* display, GLXDrawable drawable) +{ + BEFORE_GLX_CALL; + xSwapBuffersInternal(display, drawable); + AFTER_GLX_CALL; +} + +const char* +GLXLibrary::xQueryExtensionsString(Display* display, + int screen) +{ + BEFORE_GLX_CALL; + const char* result = xQueryExtensionsStringInternal(display, screen); + AFTER_GLX_CALL; + return result; +} + +const char* +GLXLibrary::xGetClientString(Display* display, + int screen) +{ + BEFORE_GLX_CALL; + const char* result = xGetClientStringInternal(display, screen); + AFTER_GLX_CALL; + return result; +} + +const char* +GLXLibrary::xQueryServerString(Display* display, + int screen, int name) +{ + BEFORE_GLX_CALL; + const char* result = xQueryServerStringInternal(display, screen, name); + AFTER_GLX_CALL; + return result; +} + +GLXPixmap +GLXLibrary::xCreatePixmap(Display* display, + GLXFBConfig config, + Pixmap pixmap, + const int* attrib_list) +{ + BEFORE_GLX_CALL; + GLXPixmap result = xCreatePixmapInternal(display, config, + pixmap, attrib_list); + AFTER_GLX_CALL; + return result; +} + +GLXPixmap +GLXLibrary::xCreateGLXPixmapWithConfig(Display* display, + GLXFBConfig config, + Pixmap pixmap) +{ + BEFORE_GLX_CALL; + GLXPixmap result = xCreateGLXPixmapWithConfigInternal(display, config, pixmap); + AFTER_GLX_CALL; + return result; +} + +void +GLXLibrary::xDestroyPixmap(Display* display, GLXPixmap pixmap) +{ + BEFORE_GLX_CALL; + xDestroyPixmapInternal(display, pixmap); + AFTER_GLX_CALL; +} + +Bool +GLXLibrary::xQueryVersion(Display* display, + int* major, + int* minor) +{ + BEFORE_GLX_CALL; + Bool result = xQueryVersionInternal(display, major, minor); + AFTER_GLX_CALL; + return result; +} + +void +GLXLibrary::xBindTexImage(Display* display, + GLXDrawable drawable, + int buffer, + const int* attrib_list) +{ + BEFORE_GLX_CALL; + xBindTexImageInternal(display, drawable, buffer, attrib_list); + AFTER_GLX_CALL; +} + +void +GLXLibrary::xReleaseTexImage(Display* display, + GLXDrawable drawable, + int buffer) +{ + BEFORE_GLX_CALL; + xReleaseTexImageInternal(display, drawable, buffer); + AFTER_GLX_CALL; +} + +void +GLXLibrary::xWaitGL() +{ + BEFORE_GLX_CALL; + xWaitGLInternal(); + AFTER_GLX_CALL; +} + +void +GLXLibrary::xWaitX() +{ + BEFORE_GLX_CALL; + xWaitXInternal(); + AFTER_GLX_CALL; +} + +GLXContext +GLXLibrary::xCreateContextAttribs(Display* display, + GLXFBConfig config, + GLXContext share_list, + Bool direct, + const int* attrib_list) +{ + BEFORE_GLX_CALL; + GLXContext result = xCreateContextAttribsInternal(display, + config, + share_list, + direct, + attrib_list); + AFTER_GLX_CALL; + return result; +} + +int +GLXLibrary::xGetVideoSync(unsigned int* count) +{ + BEFORE_GLX_CALL; + int result = xGetVideoSyncInternal(count); + AFTER_GLX_CALL; + return result; +} + +int +GLXLibrary::xWaitVideoSync(int divisor, int remainder, unsigned int* count) +{ + BEFORE_GLX_CALL; + int result = xWaitVideoSyncInternal(divisor, remainder, count); + AFTER_GLX_CALL; + return result; +} + +void +GLXLibrary::xSwapInterval(Display* display, GLXDrawable drawable, int interval) +{ + BEFORE_GLX_CALL; + xSwapIntervalInternal(display, drawable, interval); + AFTER_GLX_CALL; +} + +already_AddRefed<GLContextGLX> +GLContextGLX::CreateGLContext(CreateContextFlags flags, const SurfaceCaps& caps, + GLContextGLX* shareContext, bool isOffscreen, + Display* display, GLXDrawable drawable, GLXFBConfig cfg, + bool deleteDrawable, gfxXlibSurface* pixmap, + ContextProfile profile) +{ + GLXLibrary& glx = sGLXLibrary; + + int db = 0; + int err = glx.xGetFBConfigAttrib(display, cfg, + LOCAL_GLX_DOUBLEBUFFER, &db); + if (LOCAL_GLX_BAD_ATTRIBUTE != err) { + if (ShouldSpew()) { + printf("[GLX] FBConfig is %sdouble-buffered\n", db ? "" : "not "); + } + } + + GLXContext context; + RefPtr<GLContextGLX> glContext; + bool error; + + OffMainThreadScopedXErrorHandler xErrorHandler; + + do { + error = false; + + GLXContext glxContext = shareContext ? shareContext->mContext : nullptr; + if (glx.HasCreateContextAttribs()) { + AutoTArray<int, 11> attrib_list; + if (glx.HasRobustness()) { + int robust_attribs[] = { + LOCAL_GL_CONTEXT_FLAGS_ARB, LOCAL_GL_CONTEXT_ROBUST_ACCESS_BIT_ARB, + LOCAL_GL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_GL_LOSE_CONTEXT_ON_RESET_ARB, + }; + attrib_list.AppendElements(robust_attribs, MOZ_ARRAY_LENGTH(robust_attribs)); + } + if (profile == ContextProfile::OpenGLCore) { + int core_attribs[] = { + LOCAL_GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + LOCAL_GLX_CONTEXT_MINOR_VERSION_ARB, 2, + LOCAL_GLX_CONTEXT_FLAGS_ARB, LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + }; + attrib_list.AppendElements(core_attribs, MOZ_ARRAY_LENGTH(core_attribs)); + }; + attrib_list.AppendElement(0); + + context = glx.xCreateContextAttribs( + display, + cfg, + glxContext, + True, + attrib_list.Elements()); + } else { + context = glx.xCreateNewContext( + display, + cfg, + LOCAL_GLX_RGBA_TYPE, + glxContext, + True); + } + + if (context) { + glContext = new GLContextGLX(flags, caps, shareContext, isOffscreen, display, + drawable, context, deleteDrawable, db, pixmap, + profile); + if (!glContext->Init()) + error = true; + } else { + error = true; + } + + error |= xErrorHandler.SyncAndGetError(display); + + if (error) { + if (shareContext) { + shareContext = nullptr; + continue; + } + + NS_WARNING("Failed to create GLXContext!"); + glContext = nullptr; // note: this must be done while the graceful X error handler is set, + // because glxMakeCurrent can give a GLXBadDrawable error + } + + return glContext.forget(); + } while (true); +} + +GLContextGLX::~GLContextGLX() +{ + MarkDestroyed(); + + // Wrapped context should not destroy glxContext/Surface + if (!mOwnsContext) { + return; + } + + // see bug 659842 comment 76 +#ifdef DEBUG + bool success = +#endif + mGLX->xMakeCurrent(mDisplay, X11None, nullptr); + MOZ_ASSERT(success, + "glXMakeCurrent failed to release GL context before we call " + "glXDestroyContext!"); + + mGLX->xDestroyContext(mDisplay, mContext); + + if (mDeleteDrawable) { + mGLX->xDestroyPixmap(mDisplay, mDrawable); + } +} + + +bool +GLContextGLX::Init() +{ + SetupLookupFunction(); + if (!InitWithPrefix("gl", true)) { + 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(bool aForce) +{ + bool succeeded = true; + + // With the ATI FGLRX driver, glxMakeCurrent is very slow even when the context doesn't change. + // (This is not the case with other drivers such as NVIDIA). + // So avoid calling it more than necessary. Since GLX documentation says that: + // "glXGetCurrentContext returns client-side information. + // It does not make a round trip to the server." + // I assume that it's not worth using our own TLS slot here. + if (aForce || mGLX->xGetCurrentContext() != mContext) { + if (mGLX->IsMesa()) { + // Read into the event queue to ensure that Mesa receives a + // DRI2InvalidateBuffers event before drawing. See bug 1280653. + Unused << XPending(mDisplay); + } + + succeeded = mGLX->xMakeCurrent(mDisplay, mDrawable, mContext); + NS_ASSERTION(succeeded, "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 isASAP = (gfxPrefs::LayoutFrameRate() == 0); + mGLX->xSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1); + } + } + + return succeeded; +} + +bool +GLContextGLX::IsCurrent() { + return mGLX->xGetCurrentContext() == mContext; +} + +bool +GLContextGLX::SetupLookupFunction() +{ + mLookupFunc = (PlatformLookupFunction)&GLXLibrary::xGetProcAddress; + return true; +} + +bool +GLContextGLX::IsDoubleBuffered() const +{ + return mDoubleBuffered; +} + +bool +GLContextGLX::SupportsRobustness() const +{ + return mGLX->HasRobustness(); +} + +bool +GLContextGLX::SwapBuffers() +{ + if (!mDoubleBuffered) + return false; + mGLX->xSwapBuffers(mDisplay, mDrawable); + return true; +} + +bool +GLContextGLX::OverrideDrawable(GLXDrawable drawable) +{ + if (Screen()) + Screen()->AssureBlitted(); + Bool result = mGLX->xMakeCurrent(mDisplay, drawable, mContext); + return result; +} + +bool +GLContextGLX::RestoreDrawable() +{ + return mGLX->xMakeCurrent(mDisplay, mDrawable, mContext); +} + +GLContextGLX::GLContextGLX( + CreateContextFlags flags, + const SurfaceCaps& caps, + GLContext* shareContext, + bool isOffscreen, + Display* aDisplay, + GLXDrawable aDrawable, + GLXContext aContext, + bool aDeleteDrawable, + bool aDoubleBuffered, + gfxXlibSurface* aPixmap, + ContextProfile profile) + : GLContext(flags, caps, shareContext, isOffscreen), + mContext(aContext), + mDisplay(aDisplay), + mDrawable(aDrawable), + mDeleteDrawable(aDeleteDrawable), + mDoubleBuffered(aDoubleBuffered), + mGLX(&sGLXLibrary), + mPixmap(aPixmap), + mOwnsContext(true) +{ + MOZ_ASSERT(mGLX); + // See 899855 + SetProfileVersion(profile, 200); +} + + +static GLContextGLX* +GetGlobalContextGLX() +{ + return static_cast<GLContextGLX*>(GLContextProviderGLX::GetGlobalContext()); +} + +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; +} + +static StaticRefPtr<GLContext> gGlobalContext; + +already_AddRefed<GLContext> +GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface) +{ + if (!sGLXLibrary.EnsureInitialized()) { + return nullptr; + } + + if (aContext && aSurface) { + SurfaceCaps caps = SurfaceCaps::Any(); + RefPtr<GLContextGLX> glContext = + new GLContextGLX(CreateContextFlags::NONE, caps, + nullptr, // SharedContext + false, // Offscreen + (Display*)DefaultXDisplay(), // Display + (GLXDrawable)aSurface, (GLXContext)aContext, + false, // aDeleteDrawable, + true, + (gfxXlibSurface*)nullptr, + ContextProfile::OpenGLCompatibility); + + glContext->mOwnsContext = false; + gGlobalContext = glContext; + + return glContext.forget(); + } + + return nullptr; +} + +already_AddRefed<GLContext> +CreateForWidget(Display* aXDisplay, Window aXWindow, bool aForceAccelerated) +{ + if (!sGLXLibrary.EnsureInitialized()) { + 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; + } + + int xscreen = DefaultScreen(aXDisplay); + + ScopedXFree<GLXFBConfig> cfgs; + GLXFBConfig config; + int visid; + if (!GLContextGLX::FindFBConfigForWindow(aXDisplay, xscreen, aXWindow, &cfgs, + &config, &visid)) + { + return nullptr; + } + + SurfaceCaps caps = SurfaceCaps::Any(); + GLContextGLX* shareContext = GetGlobalContextGLX(); + RefPtr<GLContextGLX> gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE, + caps, shareContext, false, + aXDisplay, aXWindow, config, + false); + return gl.forget(); +} + +already_AddRefed<GLContext> +GLContextProviderGLX::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + X11CompositorWidget* compWidget = aCompositorWidget->AsX11(); + MOZ_ASSERT(compWidget); + + return CreateForWidget(compWidget->XDisplay(), + compWidget->XWindow(), + aForceAccelerated); +} + +already_AddRefed<GLContext> +GLContextProviderGLX::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + Display* display = (Display*)aWidget->GetNativeData(NS_NATIVE_COMPOSITOR_DISPLAY); + Window window = GET_NATIVE_WINDOW(aWidget); + + return CreateForWidget(display, + window, + aForceAccelerated); +} + +static bool +ChooseConfig(GLXLibrary* glx, Display* display, int screen, const SurfaceCaps& minCaps, + ScopedXFree<GLXFBConfig>* const out_scopedConfigArr, + GLXFBConfig* const out_config, int* const out_visid) +{ + ScopedXFree<GLXFBConfig>& scopedConfigArr = *out_scopedConfigArr; + + if (minCaps.antialias) + return false; + + int attribs[] = { + LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, + LOCAL_GLX_X_RENDERABLE, True, + LOCAL_GLX_RED_SIZE, 8, + LOCAL_GLX_GREEN_SIZE, 8, + LOCAL_GLX_BLUE_SIZE, 8, + LOCAL_GLX_ALPHA_SIZE, minCaps.alpha ? 8 : 0, + LOCAL_GLX_DEPTH_SIZE, minCaps.depth ? 16 : 0, + LOCAL_GLX_STENCIL_SIZE, minCaps.stencil ? 8 : 0, + 0 + }; + + int numConfigs = 0; + scopedConfigArr = glx->xChooseFBConfig(display, screen, attribs, &numConfigs); + 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->xGetFBConfigAttrib(display, curConfig, LOCAL_GLX_VISUAL_ID, &visid) + != Success) + { + continue; + } + + if (!visid) + continue; + + *out_config = curConfig; + *out_visid = visid; + return true; + } + + return false; +} + +bool +GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window, + ScopedXFree<GLXFBConfig>* const out_scopedConfigArr, + GLXFBConfig* const out_config, int* const out_visid) +{ + ScopedXFree<GLXFBConfig>& cfgs = *out_scopedConfigArr; + int numConfigs; + if (sGLXLibrary.IsATI() || + !sGLXLibrary.GLXVersionCheck(1, 3)) { + const int attribs[] = { + LOCAL_GLX_DOUBLEBUFFER, False, + 0 + }; + cfgs = sGLXLibrary.xChooseFBConfig(display, + screen, + attribs, + &numConfigs); + } else { + cfgs = sGLXLibrary.xGetFBConfigs(display, + screen, + &numConfigs); + } + + if (!cfgs) { + NS_WARNING("[GLX] glXGetFBConfigs() failed"); + return false; + } + NS_ASSERTION(numConfigs > 0, "No FBConfigs found!"); + + // 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; + } + 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.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid); + if (!visid) { + continue; + } + if (sGLXLibrary.IsATI()) { + 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; + } + } else { + if (windowVisualID == static_cast<VisualID>(visid)) { + *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(CreateContextFlags flags, const IntSize& size, + const SurfaceCaps& minCaps, nsACString* const out_failureId, + ContextProfile profile = ContextProfile::OpenGLCompatibility) +{ + GLXLibrary* glx = &sGLXLibrary; + if (!glx->EnsureInitialized()) + return nullptr; + + Display* display = DefaultXDisplay(); + int screen = DefaultScreen(display); + + ScopedXFree<GLXFBConfig> scopedConfigArr; + GLXFBConfig config; + int visid; + if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) { + NS_WARNING("Failed to find a compatible config."); + return nullptr; + } + + Visual* visual; + int depth; + FindVisualAndDepth(display, visid, &visual, &depth); + + OffMainThreadScopedXErrorHandler xErrorHandler; + bool error = false; + + Drawable drawable; + GLXPixmap pixmap = 0; + + gfx::IntSize dummySize(16, 16); + RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), + visual, + dummySize); + if (surface->CairoStatus() != 0) { + mozilla::Unused << xErrorHandler.SyncAndGetError(display); + 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). + drawable = surface->XDrawable(); + if (glx->GLXVersionCheck(1, 3)) { + pixmap = glx->xCreatePixmap(display, config, drawable, nullptr); + } else { + pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable); + } + + if (pixmap == 0) { + error = true; + } + + bool serverError = xErrorHandler.SyncAndGetError(display); + if (error || serverError) + return nullptr; + + GLContextGLX* shareContext = GetGlobalContextGLX(); + return GLContextGLX::CreateGLContext(flags, minCaps, shareContext, true, display, + pixmap, config, true, surface, profile); +} + +/*static*/ already_AddRefed<GLContext> +GLContextProviderGLX::CreateHeadless(CreateContextFlags flags, + nsACString* const out_failureId) +{ + IntSize dummySize = IntSize(16, 16); + SurfaceCaps dummyCaps = SurfaceCaps::Any(); + return CreateOffscreenPixmapContext(flags, dummySize, dummyCaps, out_failureId); +} + +/*static*/ already_AddRefed<GLContext> +GLContextProviderGLX::CreateOffscreen(const IntSize& size, + const SurfaceCaps& minCaps, + CreateContextFlags flags, + nsACString* const out_failureId) +{ + SurfaceCaps minBackbufferCaps = minCaps; + if (minCaps.antialias) { + minBackbufferCaps.antialias = false; + minBackbufferCaps.depth = false; + minBackbufferCaps.stencil = false; + } + + ContextProfile profile = ContextProfile::OpenGLCore; + if (flags & CreateContextFlags::REQUIRE_COMPAT_PROFILE) { + profile = ContextProfile::OpenGLCompatibility; + } + + RefPtr<GLContext> gl; + gl = CreateOffscreenPixmapContext(flags, size, minBackbufferCaps, out_failureId, + profile); + if (!gl) + return nullptr; + + if (!gl->InitOffscreen(size, minCaps)) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_GLX_INIT"); + return nullptr; + } + + return gl.forget(); +} + +/*static*/ GLContext* +GLContextProviderGLX::GetGlobalContext() +{ + // TODO: get GLX context sharing to work well with multiple threads + if (gfxEnv::DisableContextSharingGlx()) + return nullptr; + + static bool triedToCreateContext = false; + if (!triedToCreateContext) { + triedToCreateContext = true; + + MOZ_RELEASE_ASSERT(!gGlobalContext, "GFX: Global GL context already initialized."); + nsCString discardFailureId; + RefPtr<GLContext> temp = CreateHeadless(CreateContextFlags::NONE, &discardFailureId); + gGlobalContext = temp; + } + + return gGlobalContext; +} + +/*static*/ void +GLContextProviderGLX::Shutdown() +{ + gGlobalContext = nullptr; +} + +} /* namespace gl */ +} /* namespace mozilla */ + diff --git a/gfx/gl/GLContextProviderImpl.h b/gfx/gl/GLContextProviderImpl.h new file mode 100644 index 0000000000..7b63905e64 --- /dev/null +++ b/gfx/gl/GLContextProviderImpl.h @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 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(ANDROID) +typedef void* EGLSurface; +#endif // defined(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 aForceAccelerated); + + /** + * Create a context that renders to the surface of the 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 aWidget 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> + CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated); + + /** + * Create a context for offscreen rendering. The target of this + * context should be treated as opaque -- it might be a FBO, or a + * pbuffer, or some other construct. Users of this GLContext + * should bind framebuffer 0 directly to use this offscreen buffer. + * + * The offscreen context returned by this method will always have + * the ability to be rendered into a context created by a window. + * It might or might not share resources with the global context; + * query GetSharedContext() for a non-null result to check. If + * resource sharing can be avoided on the target platform, it will + * be, in order to isolate the offscreen context. + * + * @param size The initial size of this offscreen context. + * @param minCaps The required SurfaceCaps for this offscreen context. The resulting + * context *may* have more/better caps than requested, but it cannot + * have fewer/worse caps than requested. + * @param flags The set of CreateContextFlags to be used for this + * offscreen context. + * + * @return Context to use for offscreen rendering + */ + static already_AddRefed<GLContext> + CreateOffscreen(const mozilla::gfx::IntSize& size, + const SurfaceCaps& minCaps, + CreateContextFlags flags, + nsACString* const out_failureId); + + // Just create a context. We'll add offscreen stuff ourselves. + static already_AddRefed<GLContext> + CreateHeadless(CreateContextFlags flags, nsACString* const out_failureId); + + /** + * Create wrapping Gecko GLContext for external gl context. + * + * @param aContext External context which will be wrapped by Gecko GLContext. + * @param aSurface External surface which is used for external context. + * + * @return Wrapping Context to use for rendering + */ + static already_AddRefed<GLContext> + CreateWrappingExisting(void* aContext, void* aSurface); + +#if defined(ANDROID) + static EGLSurface CreateEGLSurface(void* aWindow); + static void DestroyEGLSurface(EGLSurface surface); +#endif // defined(ANDROID) + + /** + * 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/GLContextProviderNull.cpp b/gfx/gl/GLContextProviderNull.cpp new file mode 100644 index 0000000000..513ed2edad --- /dev/null +++ b/gfx/gl/GLContextProviderNull.cpp @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "GLContextProvider.h" + +namespace mozilla { +namespace gl { + +using namespace mozilla::widget; + +already_AddRefed<GLContext> +GLContextProviderNull::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + return nullptr; +} + +already_AddRefed<GLContext> +GLContextProviderNull::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + return nullptr; +} + +already_AddRefed<GLContext> +GLContextProviderNull::CreateWrappingExisting(void*, void*) +{ + return nullptr; +} + +already_AddRefed<GLContext> +GLContextProviderNull::CreateOffscreen(const gfx::IntSize&, + const SurfaceCaps&, + CreateContextFlags, + nsACString* const out_failureId) +{ + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NULL"); + return nullptr; +} + +already_AddRefed<GLContext> +GLContextProviderNull::CreateHeadless(CreateContextFlags, nsACString* const out_failureId) +{ + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NULL"); + 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..a1373f78f4 --- /dev/null +++ b/gfx/gl/GLContextProviderWGL.cpp @@ -0,0 +1,651 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "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/Preferences.h" +#include "mozilla/StaticPtr.h" +#include "mozilla/widget/CompositorWidget.h" + +namespace mozilla { +namespace gl { + +using namespace mozilla::gfx; +using namespace mozilla::widget; + +WGLLibrary sWGLLib; + +HWND +WGLLibrary::CreateDummyWindow(HDC* aWindowDC) +{ + WNDCLASSW wc; + if (!GetClassInfoW(GetModuleHandle(nullptr), L"GLContextWGLClass", &wc)) { + ZeroMemory(&wc, sizeof(WNDCLASSW)); + 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; + } + } + + HWND win = CreateWindowW(L"GLContextWGLClass", L"GLContextWGL", 0, + 0, 0, 16, 16, + nullptr, nullptr, GetModuleHandle(nullptr), + nullptr); + NS_ENSURE_TRUE(win, nullptr); + + HDC dc = GetDC(win); + NS_ENSURE_TRUE(dc, nullptr); + + if (mWindowPixelFormat == 0) { + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR)); + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cRedBits = 8; + pfd.cGreenBits = 8; + pfd.cBlueBits = 8; + pfd.cAlphaBits = 8; + pfd.cDepthBits = 0; + pfd.iLayerType = PFD_MAIN_PLANE; + + mWindowPixelFormat = ChoosePixelFormat(dc, &pfd); + } + + if (!mWindowPixelFormat || + !SetPixelFormat(dc, mWindowPixelFormat, nullptr)) + { + NS_WARNING("SetPixelFormat failed!"); + DestroyWindow(win); + return nullptr; + } + + if (aWindowDC) { + *aWindowDC = dc; + } + + return win; +} + +static inline bool +HasExtension(const char* aExtensions, const char* aRequiredExtension) +{ + return GLContext::ListHasExtension( + reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension); +} + +bool +WGLLibrary::EnsureInitialized() +{ + if (mInitialized) + return true; + + mozilla::ScopedGfxFeatureReporter reporter("WGL"); + + std::string libGLFilename = "Opengl32.dll"; + // SU_SPIES_DIRECTORY is for AMD CodeXL/gDEBugger + if (PR_GetEnv("SU_SPIES_DIRECTORY")) { + libGLFilename = std::string(PR_GetEnv("SU_SPIES_DIRECTORY")) + "\\opengl32.dll"; + } + + if (!mOGLLibrary) { + mOGLLibrary = PR_LoadLibrary(libGLFilename.c_str()); + if (!mOGLLibrary) { + NS_WARNING("Couldn't load OpenGL library."); + return false; + } + } + + const GLLibraryLoader::SymLoadStruct earlySymbols[] = { + { (PRFuncPtr*) &fCreateContext, { "wglCreateContext", nullptr } }, + { (PRFuncPtr*) &fMakeCurrent, { "wglMakeCurrent", nullptr } }, + { (PRFuncPtr*) &fGetProcAddress, { "wglGetProcAddress", nullptr } }, + { (PRFuncPtr*) &fDeleteContext, { "wglDeleteContext", nullptr } }, + { (PRFuncPtr*) &fGetCurrentContext, { "wglGetCurrentContext", nullptr } }, + { (PRFuncPtr*) &fGetCurrentDC, { "wglGetCurrentDC", nullptr } }, + { nullptr, { nullptr } } + }; + + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &earlySymbols[0])) { + NS_WARNING("Couldn't find required entry points in OpenGL DLL (early init)"); + return false; + } + + // This is ridiculous -- we have to actually create a context to + // get the OpenGL ICD to load. + mWindow = CreateDummyWindow(&mWindowDC); + NS_ENSURE_TRUE(mWindow, false); + + // create rendering context + mWindowGLContext = fCreateContext(mWindowDC); + NS_ENSURE_TRUE(mWindowGLContext, false); + + if (!fMakeCurrent(mWindowDC, mWindowGLContext)) { + NS_WARNING("wglMakeCurrent failed"); + return false; + } + + const auto curCtx = fGetCurrentContext(); + const auto curDC = fGetCurrentDC(); + + const auto lookupFunc = (GLLibraryLoader::PlatformLookupFunction)fGetProcAddress; + + // Now we can grab all the other symbols that we couldn't without having + // a context current. + const GLLibraryLoader::SymLoadStruct pbufferSymbols[] = { + { (PRFuncPtr*) &fCreatePbuffer, { "wglCreatePbufferARB", "wglCreatePbufferEXT", nullptr } }, + { (PRFuncPtr*) &fDestroyPbuffer, { "wglDestroyPbufferARB", "wglDestroyPbufferEXT", nullptr } }, + { (PRFuncPtr*) &fGetPbufferDC, { "wglGetPbufferDCARB", "wglGetPbufferDCEXT", nullptr } }, + { (PRFuncPtr*) &fBindTexImage, { "wglBindTexImageARB", "wglBindTexImageEXT", nullptr } }, + { (PRFuncPtr*) &fReleaseTexImage, { "wglReleaseTexImageARB", "wglReleaseTexImageEXT", nullptr } }, + { nullptr, { nullptr } } + }; + + const GLLibraryLoader::SymLoadStruct pixFmtSymbols[] = { + { (PRFuncPtr*) &fChoosePixelFormat, { "wglChoosePixelFormatARB", "wglChoosePixelFormatEXT", nullptr } }, + { (PRFuncPtr*) &fGetPixelFormatAttribiv, { "wglGetPixelFormatAttribivARB", "wglGetPixelFormatAttribivEXT", nullptr } }, + { nullptr, { nullptr } } + }; + + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pbufferSymbols[0], lookupFunc)) { + // this isn't an error, just means that pbuffers aren't supported + fCreatePbuffer = nullptr; + } + + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &pixFmtSymbols[0], lookupFunc)) { + // this isn't an error, just means that we don't have the pixel format extension + fChoosePixelFormat = nullptr; + } + + const GLLibraryLoader::SymLoadStruct extensionsSymbols[] = { + { (PRFuncPtr*) &fGetExtensionsString, { "wglGetExtensionsStringARB", nullptr} }, + { nullptr, { nullptr } } + }; + + const GLLibraryLoader::SymLoadStruct robustnessSymbols[] = { + { (PRFuncPtr*) &fCreateContextAttribs, { "wglCreateContextAttribsARB", nullptr} }, + { nullptr, { nullptr } } + }; + + const GLLibraryLoader::SymLoadStruct dxInteropSymbols[] = { + { (PRFuncPtr*)&fDXSetResourceShareHandle,{ "wglDXSetResourceShareHandleNV", nullptr } }, + { (PRFuncPtr*)&fDXOpenDevice, { "wglDXOpenDeviceNV", nullptr } }, + { (PRFuncPtr*)&fDXCloseDevice, { "wglDXCloseDeviceNV", nullptr } }, + { (PRFuncPtr*)&fDXRegisterObject, { "wglDXRegisterObjectNV", nullptr } }, + { (PRFuncPtr*)&fDXUnregisterObject, { "wglDXUnregisterObjectNV", nullptr } }, + { (PRFuncPtr*)&fDXObjectAccess, { "wglDXObjectAccessNV", nullptr } }, + { (PRFuncPtr*)&fDXLockObjects, { "wglDXLockObjectsNV", nullptr } }, + { (PRFuncPtr*)&fDXUnlockObjects, { "wglDXUnlockObjectsNV", nullptr } }, + { nullptr, { nullptr } } + }; + + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &extensionsSymbols[0], lookupFunc)) { + const char* extString = fGetExtensionsString(mWindowDC); + MOZ_ASSERT(extString); + MOZ_ASSERT(HasExtension(extString, "WGL_ARB_extensions_string")); + + if (HasExtension(extString, "WGL_ARB_create_context")) { + if (GLLibraryLoader::LoadSymbols(mOGLLibrary, &robustnessSymbols[0], lookupFunc)) { + if (HasExtension(extString, "WGL_ARB_create_context_robustness")) { + mHasRobustness = true; + } + } else { + NS_ERROR("WGL supports ARB_create_context without supplying its functions."); + fCreateContextAttribs = nullptr; + } + } + + //// + + mHasDXInterop = HasExtension(extString, "WGL_NV_DX_interop"); + mHasDXInterop2 = HasExtension(extString, "WGL_NV_DX_interop2"); + + nsCString blocklistId; + if (gfxUtils::IsFeatureBlacklisted(nullptr, nsIGfxInfo::FEATURE_DX_INTEROP2, + &blocklistId) && + !gfxPrefs::IgnoreDXInterop2Blacklist()) + { + mHasDXInterop2 = false; + } + + if (mHasDXInterop || mHasDXInterop2) { + if (!GLLibraryLoader::LoadSymbols(mOGLLibrary, &dxInteropSymbols[0], + lookupFunc)) + { + NS_ERROR("WGL supports NV_DX_interop(2) without supplying its functions."); + fDXSetResourceShareHandle = nullptr; + fDXOpenDevice = nullptr; + fDXCloseDevice = nullptr; + fDXRegisterObject = nullptr; + fDXUnregisterObject = nullptr; + fDXObjectAccess = nullptr; + fDXLockObjects = nullptr; + fDXUnlockObjects = nullptr; + + mHasDXInterop = false; + mHasDXInterop2 = false; + } + } + } + + // reset back to the previous context, just in case + fMakeCurrent(curDC, curCtx); + + if (mHasRobustness) { + fDeleteContext(mWindowGLContext); + + 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 + }; + + mWindowGLContext = fCreateContextAttribs(mWindowDC, nullptr, attribs); + if (!mWindowGLContext) { + mHasRobustness = false; + mWindowGLContext = fCreateContext(mWindowDC); + } + } + + mInitialized = true; + + reporter.SetSuccessful(); + return true; +} + +GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps, + bool isOffscreen, HDC aDC, HGLRC aContext, HWND aWindow) + : GLContext(flags, caps, nullptr, isOffscreen), + mDC(aDC), + mContext(aContext), + mWnd(aWindow), + mPBuffer(nullptr), + mPixelFormat(0), + mIsDoubleBuffered(false) +{ + // See 899855 + SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); +} + +GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps, + bool isOffscreen, HANDLE aPbuffer, HDC aDC, HGLRC aContext, + int aPixelFormat) + : GLContext(flags, caps, nullptr, isOffscreen), + mDC(aDC), + mContext(aContext), + mWnd(nullptr), + mPBuffer(aPbuffer), + mPixelFormat(aPixelFormat), + mIsDoubleBuffered(false) +{ + // See 899855 + SetProfileVersion(ContextProfile::OpenGLCompatibility, 200); +} + +GLContextWGL::~GLContextWGL() +{ + MarkDestroyed(); + + sWGLLib.fDeleteContext(mContext); + + if (mPBuffer) + sWGLLib.fDestroyPbuffer(mPBuffer); + if (mWnd) + DestroyWindow(mWnd); +} + +bool +GLContextWGL::Init() +{ + if (!mDC || !mContext) + return false; + + // see bug 929506 comment 29. wglGetProcAddress requires a current context. + if (!sWGLLib.fMakeCurrent(mDC, mContext)) + return false; + + SetupLookupFunction(); + if (!InitWithPrefix("gl", true)) + return false; + + return true; +} + +bool +GLContextWGL::MakeCurrentImpl(bool aForce) +{ + BOOL succeeded = true; + + // wglGetCurrentContext seems to just pull the HGLRC out + // of its TLS slot, so no need to do our own tls slot. + // You would think that wglMakeCurrent would avoid doing + // work if mContext was already current, but not so much.. + if (aForce || sWGLLib.fGetCurrentContext() != mContext) { + succeeded = sWGLLib.fMakeCurrent(mDC, mContext); + NS_ASSERTION(succeeded, "Failed to make GL context current!"); + } + + return succeeded; +} + +bool +GLContextWGL::IsCurrent() +{ + return sWGLLib.fGetCurrentContext() == mContext; +} + +void +GLContextWGL::SetIsDoubleBuffered(bool aIsDB) +{ + mIsDoubleBuffered = aIsDB; +} + +bool +GLContextWGL::IsDoubleBuffered() const +{ + return mIsDoubleBuffered; +} + +bool +GLContextWGL::SupportsRobustness() const +{ + return sWGLLib.HasRobustness(); +} + +bool +GLContextWGL::SwapBuffers() { + if (!mIsDoubleBuffered) + return false; + return ::SwapBuffers(mDC); +} + +bool +GLContextWGL::SetupLookupFunction() +{ + // Make sure that we have a ref to the OGL library; + // when run under CodeXL, wglGetProcAddress won't return + // the right thing for some core functions. + MOZ_ASSERT(mLibrary == nullptr); + + mLibrary = sWGLLib.GetOGLLibrary(); + mLookupFunc = (PlatformLookupFunction)sWGLLib.fGetProcAddress; + return true; +} + +static bool +GetMaxSize(HDC hDC, int format, IntSize& size) +{ + int query[] = {LOCAL_WGL_MAX_PBUFFER_WIDTH_ARB, LOCAL_WGL_MAX_PBUFFER_HEIGHT_ARB}; + int result[2]; + + // (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int* piValues) + if (!sWGLLib.fGetPixelFormatAttribiv(hDC, format, 0, 2, query, result)) + return false; + + size.width = result[0]; + size.height = result[1]; + return true; +} + +static bool +IsValidSizeForFormat(HDC hDC, int format, + const IntSize& requested) +{ + IntSize max; + if (!GetMaxSize(hDC, format, max)) + return true; + + if (requested.width > max.width) + return false; + if (requested.height > max.height) + return false; + + return true; +} + +static GLContextWGL* +GetGlobalContextWGL() +{ + return static_cast<GLContextWGL*>(GLContextProviderWGL::GetGlobalContext()); +} + +already_AddRefed<GLContext> +GLContextProviderWGL::CreateWrappingExisting(void*, void*) +{ + return nullptr; +} + +already_AddRefed<GLContext> +GLContextProviderWGL::CreateForCompositorWidget(CompositorWidget* aCompositorWidget, bool aForceAccelerated) +{ + return CreateForWindow(aCompositorWidget->RealWidget(), aForceAccelerated); +} + +already_AddRefed<GLContext> +GLContextProviderWGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) +{ + if (!sWGLLib.EnsureInitialized()) { + return nullptr; + } + + /** + * We need to make sure we call SetPixelFormat -after- calling + * EnsureInitialized, otherwise it can load/unload the dll and + * wglCreateContext will fail. + */ + + HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC); + + SetPixelFormat(dc, sWGLLib.GetWindowPixelFormat(), nullptr); + HGLRC context; + + if (sWGLLib.HasRobustness()) { + 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 + }; + + context = sWGLLib.fCreateContextAttribs(dc, nullptr, attribs); + } else { + context = sWGLLib.fCreateContext(dc); + } + + if (!context) { + return nullptr; + } + + SurfaceCaps caps = SurfaceCaps::ForRGBA(); + RefPtr<GLContextWGL> glContext = new GLContextWGL(CreateContextFlags::NONE, caps, + false, dc, context); + if (!glContext->Init()) { + return nullptr; + } + + glContext->SetIsDoubleBuffered(true); + + return glContext.forget(); +} + +static already_AddRefed<GLContextWGL> +CreatePBufferOffscreenContext(CreateContextFlags flags, const IntSize& aSize) +{ + WGLLibrary& wgl = sWGLLib; + + const int pfAttribs[] = { + LOCAL_WGL_SUPPORT_OPENGL_ARB, LOCAL_GL_TRUE, + LOCAL_WGL_ACCELERATION_ARB, LOCAL_WGL_FULL_ACCELERATION_ARB, + + LOCAL_WGL_DRAW_TO_PBUFFER_ARB, LOCAL_GL_TRUE, + LOCAL_WGL_DOUBLE_BUFFER_ARB, LOCAL_GL_FALSE, + LOCAL_WGL_STEREO_ARB, LOCAL_GL_FALSE, + + 0 + }; + + // We only need one! + static const uint32_t kMaxFormats = 1024; + int formats[kMaxFormats]; + uint32_t foundFormats; + HDC windowDC = wgl.GetWindowDC(); + if (!wgl.fChoosePixelFormat(windowDC, pfAttribs, nullptr, kMaxFormats, formats, + &foundFormats) + || foundFormats == 0) + { + return nullptr; + } + + // We don't care; just pick the first one. + int chosenFormat = formats[0]; + if (!IsValidSizeForFormat(windowDC, chosenFormat, aSize)) + return nullptr; + + const int pbAttribs[] = { 0 }; + HANDLE pbuffer = wgl.fCreatePbuffer(windowDC, chosenFormat, aSize.width, aSize.height, + pbAttribs); + if (!pbuffer) { + return nullptr; + } + + HDC pbdc = wgl.fGetPbufferDC(pbuffer); + NS_ASSERTION(pbdc, "expected a dc"); + + HGLRC context; + if (wgl.HasRobustness()) { + 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 + }; + context = wgl.fCreateContextAttribs(pbdc, nullptr, attribs); + } else { + context = wgl.fCreateContext(pbdc); + } + + if (!context) { + wgl.fDestroyPbuffer(pbuffer); + return nullptr; + } + + SurfaceCaps dummyCaps = SurfaceCaps::Any(); + RefPtr<GLContextWGL> glContext = new GLContextWGL(flags, dummyCaps, true, pbuffer, + pbdc, context, chosenFormat); + return glContext.forget(); +} + +static already_AddRefed<GLContextWGL> +CreateWindowOffscreenContext() +{ + HDC dc; + HWND win = sWGLLib.CreateDummyWindow(&dc); + if (!win) { + return nullptr; + } + + HGLRC context = sWGLLib.fCreateContext(dc); + if (sWGLLib.HasRobustness()) { + 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 + }; + + context = sWGLLib.fCreateContextAttribs(dc, nullptr, attribs); + } else { + context = sWGLLib.fCreateContext(dc); + } + + if (!context) { + return nullptr; + } + + SurfaceCaps caps = SurfaceCaps::ForRGBA(); + RefPtr<GLContextWGL> glContext = new GLContextWGL(CreateContextFlags::NONE, caps, + true, dc, context, win); + return glContext.forget(); +} + +/*static*/ already_AddRefed<GLContext> +GLContextProviderWGL::CreateHeadless(CreateContextFlags flags, + nsACString* const out_failureId) +{ + if (!sWGLLib.EnsureInitialized()) { + return nullptr; + } + + RefPtr<GLContextWGL> glContext; + + // Always try to create a pbuffer context first, because we + // want the context isolation. + if (sWGLLib.fCreatePbuffer && + sWGLLib.fChoosePixelFormat) + { + IntSize dummySize = IntSize(16, 16); + glContext = CreatePBufferOffscreenContext(flags, dummySize); + } + + // If it failed, then create a window context and use a FBO. + if (!glContext) { + glContext = CreateWindowOffscreenContext(); + } + + if (!glContext || + !glContext->Init()) + { + return nullptr; + } + + RefPtr<GLContext> retGL = glContext.get(); + return retGL.forget(); +} + +/*static*/ already_AddRefed<GLContext> +GLContextProviderWGL::CreateOffscreen(const IntSize& size, + const SurfaceCaps& minCaps, + CreateContextFlags flags, + nsACString* const out_failureId) +{ + RefPtr<GLContext> gl = CreateHeadless(flags, out_failureId); + if (!gl) + return nullptr; + + if (!gl->InitOffscreen(size, minCaps)) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WGL_INIT"); + return nullptr; + } + + return gl.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..61069e3f73 --- /dev/null +++ b/gfx/gl/GLContextSymbols.h @@ -0,0 +1,705 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 +{ + GLContextSymbols() { + Zero(); + } + + void Zero() { + memset(this, 0, sizeof(GLContextSymbols)); + } + + typedef void (GLAPIENTRY * PFNGLACTIVETEXTUREPROC) (GLenum texture); + PFNGLACTIVETEXTUREPROC fActiveTexture; + typedef void (GLAPIENTRY * PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); + PFNGLATTACHSHADERPROC fAttachShader; + typedef void (GLAPIENTRY * PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); + PFNGLBEGINQUERYPROC fBeginQuery; + typedef void (GLAPIENTRY * PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar* name); + PFNGLBINDATTRIBLOCATIONPROC fBindAttribLocation; + typedef void (GLAPIENTRY * PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); + PFNGLBINDBUFFERPROC fBindBuffer; + typedef void (GLAPIENTRY * PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); + PFNGLBINDTEXTUREPROC fBindTexture; + typedef void (GLAPIENTRY * PFNGLBINDVERTEXARRAYPROC) (GLuint array); + PFNGLBINDVERTEXARRAYPROC fBindVertexArray; + typedef void (GLAPIENTRY * PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + PFNGLBLENDCOLORPROC fBlendColor; + typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONPROC) (GLenum mode); + PFNGLBLENDEQUATIONPROC fBlendEquation; + typedef void (GLAPIENTRY * PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum, GLenum); + PFNGLBLENDEQUATIONSEPARATEPROC fBlendEquationSeparate; + typedef void (GLAPIENTRY * PFNGLBLENDFUNCPROC) (GLenum, GLenum); + PFNGLBLENDFUNCPROC fBlendFunc; + typedef void (GLAPIENTRY * PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + PFNGLBLENDFUNCSEPARATEPROC fBlendFuncSeparate; + typedef void (GLAPIENTRY * PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); + PFNGLBUFFERDATAPROC fBufferData; + typedef void (GLAPIENTRY * PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); + PFNGLBUFFERSUBDATAPROC fBufferSubData; + typedef void (GLAPIENTRY * PFNGLCLEARPROC) (GLbitfield); + PFNGLCLEARPROC fClear; + typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + PFNGLCLEARBUFFERFIPROC fClearBufferfi; + typedef void (GLAPIENTRY * PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat* value); + PFNGLCLEARBUFFERFVPROC fClearBufferfv; + typedef void (GLAPIENTRY * PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint* value); + PFNGLCLEARBUFFERIVPROC fClearBufferiv; + typedef void (GLAPIENTRY * PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint* value); + PFNGLCLEARBUFFERUIVPROC fClearBufferuiv; + typedef void (GLAPIENTRY * PFNGLCLEARCOLORPROC) (GLfloat, GLfloat, GLfloat, GLfloat); + PFNGLCLEARCOLORPROC fClearColor; + typedef void (GLAPIENTRY * PFNGLCLEARSTENCILPROC) (GLint); + PFNGLCLEARSTENCILPROC fClearStencil; + typedef void (GLAPIENTRY * PFNGLCOLORMASKPROC) (realGLboolean red, realGLboolean green, realGLboolean blue, realGLboolean alpha); + PFNGLCOLORMASKPROC fColorMask; + typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE2D) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* pixels); + PFNGLCOMPRESSEDTEXIMAGE2D fCompressedTexImage2D; + typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* pixels); + PFNGLCOMPRESSEDTEXSUBIMAGE2D fCompressedTexSubImage2D; + typedef void (GLAPIENTRY * PFNGLCULLFACEPROC) (GLenum mode); + PFNGLCULLFACEPROC fCullFace; + typedef void (GLAPIENTRY * PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); + PFNGLDETACHSHADERPROC fDetachShader; + typedef void (GLAPIENTRY * PFNGLDEPTHFUNCPROC) (GLenum); + PFNGLDEPTHFUNCPROC fDepthFunc; + typedef void (GLAPIENTRY * PFNGLDEPTHMASKPROC) (realGLboolean); + PFNGLDEPTHMASKPROC fDepthMask; + typedef void (GLAPIENTRY * PFNGLDISABLEPROC) (GLenum); + PFNGLDISABLEPROC fDisable; + typedef void (GLAPIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint); + PFNGLDISABLEVERTEXATTRIBARRAYPROC fDisableVertexAttribArray; + typedef void (GLAPIENTRY * PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); + PFNGLDRAWARRAYSPROC fDrawArrays; + typedef void (GLAPIENTRY * PFNGLDRAWBUFFERPROC) (GLenum mode); + PFNGLDRAWBUFFERPROC fDrawBuffer; + typedef void (GLAPIENTRY * PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum* bufs); + PFNGLDRAWBUFFERSPROC fDrawBuffers; + typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); + PFNGLDRAWELEMENTSPROC fDrawElements; + typedef void (GLAPIENTRY * PFNGLENABLEPROC) (GLenum); + PFNGLENABLEPROC fEnable; + typedef void (GLAPIENTRY * PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint); + PFNGLENABLEVERTEXATTRIBARRAYPROC fEnableVertexAttribArray; + typedef void (GLAPIENTRY * PFNGLFINISHPROC) (void); + PFNGLFINISHPROC fFinish; + typedef void (GLAPIENTRY * PFNGLENDQUERYPROC) (GLenum target); + PFNGLENDQUERYPROC fEndQuery; + typedef void (GLAPIENTRY * PFNGLFLUSHPROC) (void); + PFNGLFLUSHPROC fFlush; + typedef void (GLAPIENTRY * PFNGLFRONTFACEPROC) (GLenum); + PFNGLFRONTFACEPROC fFrontFace; + typedef void (GLAPIENTRY * PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); + PFNGLGETACTIVEATTRIBPROC fGetActiveAttrib; + typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name); + PFNGLGETACTIVEUNIFORMPROC fGetActiveUniform; + typedef void (GLAPIENTRY * PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders); + PFNGLGETATTACHEDSHADERSPROC fGetAttachedShaders; + typedef GLint (GLAPIENTRY * PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar* name); + PFNGLGETATTRIBLOCATIONPROC fGetAttribLocation; + typedef void (GLAPIENTRY * PFNGLGETINTEGERVPROC) (GLenum pname, GLint* params); + PFNGLGETINTEGERVPROC fGetIntegerv; + typedef void (GLAPIENTRY * PFNGLGETFLOATVPROC) (GLenum pname, GLfloat* params); + PFNGLGETFLOATVPROC fGetFloatv; + typedef void (GLAPIENTRY * PFNGLGETBOOLEANBPROC) (GLenum pname, realGLboolean* params); + PFNGLGETBOOLEANBPROC fGetBooleanv; + typedef void (GLAPIENTRY * PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); + PFNGLGETBUFFERPARAMETERIVPROC fGetBufferParameteriv; + typedef void (GLAPIENTRY * PFNGLGENERATEMIPMAPPROC) (GLenum target); + PFNGLGENERATEMIPMAPPROC fGenerateMipmap; + typedef GLenum (GLAPIENTRY * PFNGLGETERRORPROC) (void); + PFNGLGETERRORPROC fGetError; + typedef void (GLAPIENTRY * PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint* param); + PFNGLGETPROGRAMIVPROC fGetProgramiv; + typedef void (GLAPIENTRY * PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog); + PFNGLGETPROGRAMINFOLOGPROC fGetProgramInfoLog; + typedef void (GLAPIENTRY * PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint* params); + PFNGLGETQUERYIVPROC fGetQueryiv; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTIVPROC) (GLuint id, GLenum pname, GLint* params); + PFNGLGETQUERYOBJECTIVPROC fGetQueryObjectiv; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint* params); + PFNGLGETQUERYOBJECTUIVPROC fGetQueryObjectuiv; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTI64VPROC) (GLuint id, GLenum pname, GLint64* params); + PFNGLGETQUERYOBJECTI64VPROC fGetQueryObjecti64v; + typedef void (GLAPIENTRY * PFNGLGETQUERYOBJECTUI64VPROC) (GLuint id, GLenum pname, GLuint64* params); + PFNGLGETQUERYOBJECTUI64VPROC fGetQueryObjectui64v; + typedef void (GLAPIENTRY * PFNGLQUERYCOUNTERPROC) (GLuint id, GLenum target); + PFNGLQUERYCOUNTERPROC fQueryCounter; + typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); + PFNGLTEXPARAMETERIPROC fTexParameteri; + typedef void (GLAPIENTRY * PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint* param); + PFNGLTEXPARAMETERIVPROC fTexParameteriv; + typedef void (GLAPIENTRY * PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param); + PFNGLTEXPARAMETERFPROC fTexParameterf; + typedef GLubyte* (GLAPIENTRY * PFNGLGETSTRINGPROC) (GLenum); + PFNGLGETSTRINGPROC fGetString; + typedef void (GLAPIENTRY * PFNGLGETTEXIMAGEPROC) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid* image); + PFNGLGETTEXIMAGEPROC fGetTexImage; + typedef void (GLAPIENTRY * PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint* params); + PFNGLGETTEXLEVELPARAMETERIVPROC fGetTexLevelParameteriv; + typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat* params); + PFNGLGETTEXPARAMETERFVPROC fGetTexParameterfv; + typedef void (GLAPIENTRY * PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint* params); + PFNGLGETTEXPARAMETERIVPROC fGetTexParameteriv; + typedef void (GLAPIENTRY * PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat* params); + PFNGLGETUNIFORMFVPROC fGetUniformfv; + typedef void (GLAPIENTRY * PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint* params); + PFNGLGETUNIFORMIVPROC fGetUniformiv; + typedef void (GLAPIENTRY * PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint* params); + PFNGLGETUNIFORMUIVPROC fGetUniformuiv; + typedef GLint (GLAPIENTRY * PFNGLGETUNIFORMLOCATIONPROC) (GLint programObj, const GLchar* name); + PFNGLGETUNIFORMLOCATIONPROC fGetUniformLocation; + typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBFVPROC) (GLuint, GLenum, GLfloat*); + PFNGLGETVERTEXATTRIBFVPROC fGetVertexAttribfv; + typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIVPROC) (GLuint, GLenum, GLint*); + PFNGLGETVERTEXATTRIBIVPROC fGetVertexAttribiv; + typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint, GLenum, GLvoid**); + PFNGLGETVERTEXATTRIBPOINTERVPROC fGetVertexAttribPointerv; + typedef void (GLAPIENTRY * PFNGLHINTPROC) (GLenum target, GLenum mode); + PFNGLHINTPROC fHint; + typedef realGLboolean (GLAPIENTRY * PFNGLISBUFFERPROC) (GLuint buffer); + PFNGLISBUFFERPROC fIsBuffer; + typedef realGLboolean (GLAPIENTRY * PFNGLISENABLEDPROC) (GLenum cap); + PFNGLISENABLEDPROC fIsEnabled; + typedef realGLboolean (GLAPIENTRY * PFNGLISPROGRAMPROC) (GLuint program); + PFNGLISPROGRAMPROC fIsProgram; + typedef realGLboolean (GLAPIENTRY * PFNGLISQUERYPROC) (GLuint id); + PFNGLISQUERYPROC fIsQuery; + typedef realGLboolean (GLAPIENTRY * PFNGLISSHADERPROC) (GLuint shader); + PFNGLISSHADERPROC fIsShader; + typedef realGLboolean (GLAPIENTRY * PFNGLISTEXTUREPROC) (GLuint texture); + PFNGLISTEXTUREPROC fIsTexture; + typedef void (GLAPIENTRY * PFNGLLINEWIDTHPROC) (GLfloat width); + PFNGLLINEWIDTHPROC fLineWidth; + typedef void (GLAPIENTRY * PFNGLLINKPROGRAMPROC) (GLuint program); + PFNGLLINKPROGRAMPROC fLinkProgram; + typedef void (GLAPIENTRY * PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); + PFNGLPIXELSTOREIPROC fPixelStorei; + typedef void (GLAPIENTRY * PFNGLPOINTPARAMETERFPROC) (GLenum pname, GLfloat param); + PFNGLPOINTPARAMETERFPROC fPointParameterf; + typedef void (GLAPIENTRY * PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat bias); + PFNGLPOLYGONOFFSETPROC fPolygonOffset; + typedef void (GLAPIENTRY * PFNGLREADBUFFERPROC) (GLenum); + PFNGLREADBUFFERPROC fReadBuffer; + typedef void (GLAPIENTRY * PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + PFNGLREADPIXELSPROC fReadPixels; + typedef void (GLAPIENTRY * PFNGLSAMPLECOVERAGEPROC) (GLclampf value, realGLboolean invert); + PFNGLSAMPLECOVERAGEPROC fSampleCoverage; + typedef void (GLAPIENTRY * PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask); + PFNGLSTENCILFUNCPROC fStencilFunc; + typedef void (GLAPIENTRY * PFNGLSTENCILFUNCSEPARATEPROC) (GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask); + PFNGLSTENCILFUNCSEPARATEPROC fStencilFuncSeparate; + typedef void (GLAPIENTRY * PFNGLSTENCILMASKPROC) (GLuint mask); + PFNGLSTENCILMASKPROC fStencilMask; + typedef void (GLAPIENTRY * PFNGLSTENCILMASKSEPARATEPROC) (GLenum, GLuint); + PFNGLSTENCILMASKSEPARATEPROC fStencilMaskSeparate; + typedef void (GLAPIENTRY * PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass); + PFNGLSTENCILOPPROC fStencilOp; + typedef void (GLAPIENTRY * PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + PFNGLSTENCILOPSEPARATEPROC fStencilOpSeparate; + typedef void (GLAPIENTRY * PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); + PFNGLTEXIMAGE2DPROC fTexImage2D; + typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels); + PFNGLTEXSUBIMAGE2DPROC fTexSubImage2D; + typedef void (GLAPIENTRY * PFNGLTEXTURERANGEAPPLEPROC) (GLenum target, GLsizei length, GLvoid* pointer); + PFNGLTEXTURERANGEAPPLEPROC fTextureRangeAPPLE; + typedef void (GLAPIENTRY * PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); + PFNGLUNIFORM1FPROC fUniform1f; + typedef void (GLAPIENTRY * PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat* value); + PFNGLUNIFORM1FVPROC fUniform1fv; + typedef void (GLAPIENTRY * PFNGLUNIFORM1IPROC) (GLint location, GLint v0); + PFNGLUNIFORM1IPROC fUniform1i; + typedef void (GLAPIENTRY * PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint* value); + PFNGLUNIFORM1IVPROC fUniform1iv; + typedef void (GLAPIENTRY * PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); + PFNGLUNIFORM2FPROC fUniform2f; + typedef void (GLAPIENTRY * PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat* value); + PFNGLUNIFORM2FVPROC fUniform2fv; + typedef void (GLAPIENTRY * PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); + PFNGLUNIFORM2IPROC fUniform2i; + typedef void (GLAPIENTRY * PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint* value); + PFNGLUNIFORM2IVPROC fUniform2iv; + typedef void (GLAPIENTRY * PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + PFNGLUNIFORM3FPROC fUniform3f; + typedef void (GLAPIENTRY * PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat* value); + PFNGLUNIFORM3FVPROC fUniform3fv; + typedef void (GLAPIENTRY * PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); + PFNGLUNIFORM3IPROC fUniform3i; + typedef void (GLAPIENTRY * PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint* value); + PFNGLUNIFORM3IVPROC fUniform3iv; + typedef void (GLAPIENTRY * PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + PFNGLUNIFORM4FPROC fUniform4f; + typedef void (GLAPIENTRY * PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat* value); + PFNGLUNIFORM4FVPROC fUniform4fv; + typedef void (GLAPIENTRY * PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + PFNGLUNIFORM4IPROC fUniform4i; + typedef void (GLAPIENTRY * PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint* value); + PFNGLUNIFORM4IVPROC fUniform4iv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX2FVPROC fUniformMatrix2fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX2X3FVPROC fUniformMatrix2x3fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX2X4FVPROC fUniformMatrix2x4fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX3FVPROC fUniformMatrix3fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX3X2FVPROC fUniformMatrix3x2fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX3X4FVPROC fUniformMatrix3x4fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX4FVPROC fUniformMatrix4fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX4X2FVPROC fUniformMatrix4x2fv; + typedef void (GLAPIENTRY * PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value); + PFNGLUNIFORMMATRIX4X3FVPROC fUniformMatrix4x3fv; + + typedef void (GLAPIENTRY * PFNGLUSEPROGRAMPROC) (GLuint program); + PFNGLUSEPROGRAMPROC fUseProgram; + typedef void (GLAPIENTRY * PFNGLVALIDATEPROGRAMPROC) (GLuint program); + PFNGLVALIDATEPROGRAMPROC fValidateProgram; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, realGLboolean normalized, GLsizei stride, const GLvoid* pointer); + PFNGLVERTEXATTRIBPOINTERPROC fVertexAttribPointer; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); + PFNGLVERTEXATTRIB1FPROC fVertexAttrib1f; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); + PFNGLVERTEXATTRIB2FPROC fVertexAttrib2f; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); + PFNGLVERTEXATTRIB3FPROC fVertexAttrib3f; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + PFNGLVERTEXATTRIB4FPROC fVertexAttrib4f; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat* v); + PFNGLVERTEXATTRIB1FVPROC fVertexAttrib1fv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat* v); + PFNGLVERTEXATTRIB2FVPROC fVertexAttrib2fv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat* v); + PFNGLVERTEXATTRIB3FVPROC fVertexAttrib3fv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat* v); + PFNGLVERTEXATTRIB4FVPROC fVertexAttrib4fv; + typedef void (GLAPIENTRY * PFNGLCOMPILESHADERPROC) (GLuint shader); + PFNGLCOMPILESHADERPROC fCompileShader; + typedef void (GLAPIENTRY * PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + PFNGLCOPYTEXIMAGE2DPROC fCopyTexImage2D; + typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + PFNGLCOPYTEXSUBIMAGE2DPROC fCopyTexSubImage2D; + typedef void (GLAPIENTRY * PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint* param); + PFNGLGETSHADERIVPROC fGetShaderiv; + typedef void (GLAPIENTRY * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog); + PFNGLGETSHADERINFOLOGPROC fGetShaderInfoLog; + typedef void (GLAPIENTRY * PFNGETSHADERPRECISIONFORMAT) (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); + PFNGETSHADERPRECISIONFORMAT fGetShaderPrecisionFormat; + typedef void (GLAPIENTRY * PFNGLGETSHADERSOURCEPROC) (GLint obj, GLsizei maxLength, GLsizei* length, GLchar* source); + PFNGLGETSHADERSOURCEPROC fGetShaderSource; + typedef void (GLAPIENTRY * PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar* const* strings, const GLint* lengths); + PFNGLSHADERSOURCEPROC fShaderSource; + + typedef void (GLAPIENTRY * PFNGLBINDFRAMEBUFFER) (GLenum target, GLuint framebuffer); + PFNGLBINDFRAMEBUFFER fBindFramebuffer; + typedef void (GLAPIENTRY * PFNGLBINDRENDERBUFFER) (GLenum target, GLuint renderbuffer); + PFNGLBINDRENDERBUFFER fBindRenderbuffer; + typedef GLenum (GLAPIENTRY * PFNGLCHECKFRAMEBUFFERSTATUS) (GLenum target); + PFNGLCHECKFRAMEBUFFERSTATUS fCheckFramebufferStatus; + typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERRENDERBUFFER) (GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer); + PFNGLFRAMEBUFFERRENDERBUFFER fFramebufferRenderbuffer; + typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURE2D) (GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level); + PFNGLFRAMEBUFFERTEXTURE2D fFramebufferTexture2D; + typedef void (GLAPIENTRY * PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + PFNGLFRAMEBUFFERTEXTURELAYERPROC fFramebufferTextureLayer; + typedef void (GLAPIENTRY * PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV) (GLenum target, GLenum attachment, GLenum pname, GLint* value); + PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIV fGetFramebufferAttachmentParameteriv; + typedef void (GLAPIENTRY * PFNGLGETRENDERBUFFERPARAMETERIV) (GLenum target, GLenum pname, GLint* value); + PFNGLGETRENDERBUFFERPARAMETERIV fGetRenderbufferParameteriv; + typedef realGLboolean (GLAPIENTRY * PFNGLISFRAMEBUFFER) (GLuint framebuffer); + PFNGLISFRAMEBUFFER fIsFramebuffer; + typedef realGLboolean (GLAPIENTRY * PFNGLISRENDERBUFFER) (GLuint renderbuffer); + PFNGLISRENDERBUFFER fIsRenderbuffer; + typedef realGLboolean (GLAPIENTRY * PFNGLISVERTEXARRAY) (GLuint array); + PFNGLISVERTEXARRAY fIsVertexArray; + typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGE) (GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); + PFNGLRENDERBUFFERSTORAGE fRenderbufferStorage; + + typedef void (GLAPIENTRY * PFNINVALIDATEFRAMEBUFFER) (GLenum target, GLsizei numAttachments, const GLenum* attachments); + PFNINVALIDATEFRAMEBUFFER fInvalidateFramebuffer; + typedef void (GLAPIENTRY * PFNINVALIDATESUBFRAMEBUFFER) (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); + PFNINVALIDATESUBFRAMEBUFFER fInvalidateSubFramebuffer; + + // These functions are only used by Skia/GL in desktop mode. + // Other parts of Gecko should avoid using these + typedef void (GLAPIENTRY * PFNGLCLIENTACTIVETEXTURE) (GLenum texture); + PFNGLCLIENTACTIVETEXTURE fClientActiveTexture; + typedef void (GLAPIENTRY * PFNDISABLECLIENTSTATE) (GLenum capability); + PFNDISABLECLIENTSTATE fDisableClientState; + typedef void (GLAPIENTRY * PFNENABLECLIENTSTATE) (GLenum capability); + PFNENABLECLIENTSTATE fEnableClientState; + typedef void (GLAPIENTRY * PFNLOADIDENTITY) (void); + PFNLOADIDENTITY fLoadIdentity; + typedef void (GLAPIENTRY * PFNLOADMATRIXD) (const GLdouble* matrix); + PFNLOADMATRIXD fLoadMatrixd; + typedef void (GLAPIENTRY * PFNLOADMATRIXF) (const GLfloat* matrix); + PFNLOADMATRIXF fLoadMatrixf; + typedef void (GLAPIENTRY * PFNMATRIXMODE) (GLenum mode); + PFNMATRIXMODE fMatrixMode; + typedef void (GLAPIENTRY * PFNTEXGENI) (GLenum coord, GLenum pname, GLint param); + PFNTEXGENI fTexGeni; + typedef void (GLAPIENTRY * PFNTEXGENF) (GLenum coord, GLenum pname, GLfloat param); + PFNTEXGENF fTexGenf; + typedef void (GLAPIENTRY * PFNTEXGENFV) (GLenum coord, GLenum pname, const GLfloat* param); + PFNTEXGENFV fTexGenfv; + typedef void (GLAPIENTRY * PFNVERTEXPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); + PFNVERTEXPOINTER fVertexPointer; + + typedef void (GLAPIENTRY * PFNGLBLITFRAMEBUFFER) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + PFNGLBLITFRAMEBUFFER fBlitFramebuffer; + typedef void (GLAPIENTRY * PFNGLRENDERBUFFERSTORAGEMULTISAMPLE) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height); + PFNGLRENDERBUFFERSTORAGEMULTISAMPLE fRenderbufferStorageMultisample; + + + /* These are different between GLES2 and desktop GL; we hide those differences, use the GL + * names, but the most limited data type. + */ + typedef void (GLAPIENTRY * PFNGLDEPTHRANGEFPROC) (GLclampf, GLclampf); + PFNGLDEPTHRANGEFPROC fDepthRangef; + typedef void (GLAPIENTRY * PFNGLCLEARDEPTHFPROC) (GLclampf); + PFNGLCLEARDEPTHFPROC fClearDepthf; + + typedef void (GLAPIENTRY * PFNGLDEPTHRANGEPROC) (GLclampd, GLclampd); + PFNGLDEPTHRANGEPROC fDepthRange; + typedef void (GLAPIENTRY * PFNGLCLEARDEPTHPROC) (GLclampd); + PFNGLCLEARDEPTHPROC fClearDepth; + + /* These are special because we end up tracking these so that we don't + * have to query the values from GL. + */ + + typedef void (GLAPIENTRY * PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + PFNGLVIEWPORTPROC fViewport; + typedef void (GLAPIENTRY * PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); + PFNGLSCISSORPROC fScissor; + + + /* 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. + */ + + typedef GLuint (GLAPIENTRY * PFNGLCREATEPROGRAMPROC) (void); + PFNGLCREATEPROGRAMPROC fCreateProgram; + typedef GLuint (GLAPIENTRY * PFNGLCREATESHADERPROC) (GLenum type); + PFNGLCREATESHADERPROC fCreateShader; + typedef void (GLAPIENTRY * PFNGLGENBUFFERSPROC) (GLsizei n, GLuint* buffers); + PFNGLGENBUFFERSPROC fGenBuffers; + typedef void (GLAPIENTRY * PFNGLGENQUERIESPROC) (GLsizei n, GLuint* queries); + PFNGLGENQUERIESPROC fGenQueries; + typedef void (GLAPIENTRY * PFNGLGENTEXTURESPROC) (GLsizei n, GLuint* textures); + PFNGLGENTEXTURESPROC fGenTextures; + typedef void (GLAPIENTRY * PFNGLGENFRAMEBUFFERS) (GLsizei n, GLuint* ids); + PFNGLGENFRAMEBUFFERS fGenFramebuffers; + typedef void (GLAPIENTRY * PFNGLGENRENDERBUFFERS) (GLsizei n, GLuint* ids); + PFNGLGENRENDERBUFFERS fGenRenderbuffers; + typedef void (GLAPIENTRY * PFNGLGENVERTEXARRAYS) (GLsizei n, GLuint* arrays); + PFNGLGENVERTEXARRAYS fGenVertexArrays; + + typedef void (GLAPIENTRY * PFNGLDELETEPROGRAMPROC) (GLuint program); + PFNGLDELETEPROGRAMPROC fDeleteProgram; + typedef void (GLAPIENTRY * PFNGLDELETESHADERPROC) (GLuint shader); + PFNGLDELETESHADERPROC fDeleteShader; + typedef void (GLAPIENTRY * PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint* buffers); + PFNGLDELETEBUFFERSPROC fDeleteBuffers; + typedef void (GLAPIENTRY * PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint* queries); + PFNGLDELETEQUERIESPROC fDeleteQueries; + typedef void (GLAPIENTRY * PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint* textures); + PFNGLDELETETEXTURESPROC fDeleteTextures; + typedef void (GLAPIENTRY * PFNGLDELETEFRAMEBUFFERS) (GLsizei n, const GLuint* ids); + PFNGLDELETEFRAMEBUFFERS fDeleteFramebuffers; + typedef void (GLAPIENTRY * PFNGLDELETERENDERBUFFERS) (GLsizei n, const GLuint* ids); + PFNGLDELETERENDERBUFFERS fDeleteRenderbuffers; + typedef void (GLAPIENTRY * PFNGLDELETEVERTEXARRAYS) (GLsizei n, const GLuint* arrays); + PFNGLDELETEVERTEXARRAYS fDeleteVertexArrays; + + typedef void* (GLAPIENTRY * PFNGLMAPBUFFER) (GLenum target, GLenum access); + PFNGLMAPBUFFER fMapBuffer; + typedef realGLboolean (GLAPIENTRY * PFNGLUNMAPBUFFER) (GLenum target); + PFNGLUNMAPBUFFER fUnmapBuffer; + + // ARB_copy_buffer / OpenGL 3.1 / OpenGL ES 3.0 + typedef void (GLAPIENTRY * PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, + GLintptr readOffset, GLintptr writeOffset, + GLsizeiptr size); + PFNGLCOPYBUFFERSUBDATAPROC fCopyBufferSubData; + + typedef GLenum (GLAPIENTRY * PFNGLGETGRAPHICSRESETSTATUS) (void); + PFNGLGETGRAPHICSRESETSTATUS fGetGraphicsResetStatus; + + // ARB_sync + typedef GLsync (GLAPIENTRY * PFNGLFENCESYNC) (GLenum condition, GLbitfield flags); + PFNGLFENCESYNC fFenceSync; + typedef realGLboolean (GLAPIENTRY * PFNGLISSYNC) (GLsync sync); + PFNGLISSYNC fIsSync; + typedef void (GLAPIENTRY * PFNGLDELETESYNC) (GLsync sync); + PFNGLDELETESYNC fDeleteSync; + typedef GLenum (GLAPIENTRY * PFNGLCLIENTWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + PFNGLCLIENTWAITSYNC fClientWaitSync; + typedef void (GLAPIENTRY * PFNGLWAITSYNC) (GLsync sync, GLbitfield flags, GLuint64 timeout); + PFNGLWAITSYNC fWaitSync; + typedef void (GLAPIENTRY * PFNGLGETINTEGER64V) (GLenum pname, GLint64* params); + PFNGLGETINTEGER64V fGetInteger64v; + typedef void (GLAPIENTRY * PFNGLGETSYNCIV) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); + PFNGLGETSYNCIV fGetSynciv; + + // OES_egl_image + typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETTEXTURE2D)(GLenum target, GLeglImage image); + PFNGLEGLIMAGETARGETTEXTURE2D fEGLImageTargetTexture2D; + typedef void (GLAPIENTRY * PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGE)(GLenum target, GLeglImage image); + PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGE fEGLImageTargetRenderbufferStorage; + + // ARB_draw_instanced + typedef void (GLAPIENTRY * PFNGLDRAWARRAYSINSTANCED) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); + PFNGLDRAWARRAYSINSTANCED fDrawArraysInstanced; + typedef void (GLAPIENTRY * PFNGLDRAWELEMENTSINSTANCED) (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei primcount); + PFNGLDRAWELEMENTSINSTANCED fDrawElementsInstanced; + + // ARB_instanced_array + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBDIVISOR) (GLuint index, GLuint divisor); + PFNGLVERTEXATTRIBDIVISOR fVertexAttribDivisor; + + // ARB_internalformat_query + typedef void (GLAPIENTRY * PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + PFNGLGETINTERNALFORMATIVPROC fGetInternalformativ; + + // ARB_transform_feedback2 / OpenGL 4.0 / OpenGL ES 3.0 + typedef void (GLAPIENTRY * PFNGLBINDBUFFERBASE) (GLenum target, GLuint index, GLuint buffer); + PFNGLBINDBUFFERBASE fBindBufferBase; + typedef void (GLAPIENTRY * PFNGLBINDBUFFERRANGE) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + PFNGLBINDBUFFERRANGE fBindBufferRange; + + typedef void (GLAPIENTRY * PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint* ids); + PFNGLGENTRANSFORMFEEDBACKSPROC fGenTransformFeedbacks; + typedef void (GLAPIENTRY * PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint* ids); + PFNGLDELETETRANSFORMFEEDBACKSPROC fDeleteTransformFeedbacks; + typedef realGLboolean (GLAPIENTRY * PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); + PFNGLISTRANSFORMFEEDBACKPROC fIsTransformFeedback; + typedef void (GLAPIENTRY * PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); + PFNGLBINDTRANSFORMFEEDBACKPROC fBindTransformFeedback; + typedef void (GLAPIENTRY * PFNGLTRANSFORMFEEDBACKVARYINGS) (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); + PFNGLTRANSFORMFEEDBACKVARYINGS fTransformFeedbackVaryings; + typedef void (GLAPIENTRY * PFNGLGETTRANSFORMFEEDBACKVARYING) (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); + PFNGLGETTRANSFORMFEEDBACKVARYING fGetTransformFeedbackVarying; + typedef void (GLAPIENTRY * PFNGLBEGINTRANSFORMFEEDBACK) (GLenum primitiveMode); + PFNGLBEGINTRANSFORMFEEDBACK fBeginTransformFeedback; + typedef void (GLAPIENTRY * PFNGLENDTRANSFORMFEEDBACK) (void); + PFNGLENDTRANSFORMFEEDBACK fEndTransformFeedback; + typedef void (GLAPIENTRY * PFNGLPAUSETRANSFORMFEEDBACKPROC) (); + PFNGLPAUSETRANSFORMFEEDBACKPROC fPauseTransformFeedback; + typedef void (GLAPIENTRY * PFNGLRESUMETRANSFORMFEEDBACKPROC) (); + PFNGLRESUMETRANSFORMFEEDBACKPROC fResumeTransformFeedback; + + typedef void (GLAPIENTRY * PFNGLGETINTEGERI_V) (GLenum param, GLuint index, GLint* values); + PFNGLGETINTEGERI_V fGetIntegeri_v; + typedef void (GLAPIENTRY * PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64* data); + PFNGLGETINTEGER64I_VPROC fGetInteger64i_v; + + // EXT_transform_feedback only + typedef void (GLAPIENTRY * PFNGLBINDBUFFEROFFSET) (GLenum target, GLuint index, GLuint buffer, GLintptr offset); + PFNGLBINDBUFFEROFFSET fBindBufferOffset; + + // KHR_debug + typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECONTROL) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, realGLboolean enabled); + PFNGLDEBUGMESSAGECONTROL fDebugMessageControl; + typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGEINSERT) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf); + PFNGLDEBUGMESSAGEINSERT fDebugMessageInsert; + typedef void (GLAPIENTRY * PFNGLDEBUGMESSAGECALLBACK) (GLDEBUGPROC callback, const GLvoid* userParam); + PFNGLDEBUGMESSAGECALLBACK fDebugMessageCallback; + typedef GLuint (GLAPIENTRY * PFNGLDEBUGMESSAGELOG) (GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog); + PFNGLDEBUGMESSAGELOG fGetDebugMessageLog; + typedef void (GLAPIENTRY * PFNGLGETPOINTERV) (GLenum pname, GLvoid** params); + PFNGLGETPOINTERV fGetPointerv; + typedef void (GLAPIENTRY * PFNGLPUSHDEBUGGROUP) (GLenum source, GLuint id, GLsizei length, const GLchar* message); + PFNGLPUSHDEBUGGROUP fPushDebugGroup; + typedef void (GLAPIENTRY * PFNGLPOPDEBUGGROUP) (void); + PFNGLPOPDEBUGGROUP fPopDebugGroup; + typedef void (GLAPIENTRY * PFNGLOBJECTLABEL) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label); + PFNGLOBJECTLABEL fObjectLabel; + typedef void (GLAPIENTRY * PFNGLGETOBJECTLABEL) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label); + PFNGLGETOBJECTLABEL fGetObjectLabel; + typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei length, const GLchar* label); + PFNGLOBJECTPTRLABEL fObjectPtrLabel; + typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label); + PFNGLGETOBJECTPTRLABEL fGetObjectPtrLabel; + + // draw_range_elements + typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTS) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); + PFNGLDRAWRANGEELEMENTS fDrawRangeElements; + + // NV_fence + typedef void (GLAPIENTRY * pfnGenFencesT) (GLsizei n, GLuint* fences); + pfnGenFencesT fGenFences; + typedef void (GLAPIENTRY * pfnDeleteFencesT) (GLsizei n, const GLuint* fences); + pfnDeleteFencesT fDeleteFences; + typedef void (GLAPIENTRY * pfnSetFenceT) (GLuint fence, GLenum condition); + pfnSetFenceT fSetFence; + typedef realGLboolean (GLAPIENTRY * pfnTestFenceT) (GLuint fence); + pfnTestFenceT fTestFence; + typedef void (GLAPIENTRY * pfnFinishFenceT) (GLuint fence); + pfnFinishFenceT fFinishFence; + typedef realGLboolean (GLAPIENTRY * pfnIsFenceT) (GLuint fence); + pfnIsFenceT fIsFence; + typedef void (GLAPIENTRY * pfnGetFenceivT) (GLuint fence, GLenum pname, GLint* params); + pfnGetFenceivT fGetFenceiv; + + // map_buffer_range + typedef void* (GLAPIENTRY * PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + PFNGLMAPBUFFERRANGEPROC fMapBufferRange; + typedef void (GLAPIENTRY * PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); + PFNGLFLUSHMAPPEDBUFFERRANGEPROC fFlushMappedBufferRange; + + // sampler_object + typedef void (GLAPIENTRY * PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint* samplers); + PFNGLGENSAMPLERSPROC fGenSamplers; + typedef void (GLAPIENTRY * PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint* samplers); + PFNGLDELETESAMPLERSPROC fDeleteSamplers; + typedef realGLboolean (GLAPIENTRY * PFNGLISSAMPLERPROC) (GLuint sampler); + PFNGLISSAMPLERPROC fIsSampler; + typedef void (GLAPIENTRY * PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); + PFNGLBINDSAMPLERPROC fBindSampler; + typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); + PFNGLSAMPLERPARAMETERIPROC fSamplerParameteri; + typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint* param); + PFNGLSAMPLERPARAMETERIVPROC fSamplerParameteriv; + typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); + PFNGLSAMPLERPARAMETERFPROC fSamplerParameterf; + typedef void (GLAPIENTRY * PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat* param); + PFNGLSAMPLERPARAMETERFVPROC fSamplerParameterfv; + typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint* params); + PFNGLGETSAMPLERPARAMETERIVPROC fGetSamplerParameteriv; + typedef void (GLAPIENTRY * PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat* params); + PFNGLGETSAMPLERPARAMETERFVPROC fGetSamplerParameterfv; + + // texture_storage + typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + PFNGLTEXSTORAGE2DPROC fTexStorage2D; + typedef void (GLAPIENTRY * PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + PFNGLTEXSTORAGE3DPROC fTexStorage3D; + + // uniform_buffer_object + typedef void (GLAPIENTRY * PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, + const GLchar* const* uniformNames, GLuint* uniformIndices); + PFNGLGETUNIFORMINDICESPROC fGetUniformIndices; + typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, + GLenum pname, GLint* params); + PFNGLGETACTIVEUNIFORMSIVPROC fGetActiveUniformsiv; + typedef GLuint (GLAPIENTRY * PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar* uniformBlockName); + PFNGLGETUNIFORMBLOCKINDEXPROC fGetUniformBlockIndex; + typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); + PFNGLGETACTIVEUNIFORMBLOCKIVPROC fGetActiveUniformBlockiv; + typedef void (GLAPIENTRY * PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); + PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC fGetActiveUniformBlockName; + typedef void (GLAPIENTRY * PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + PFNGLUNIFORMBLOCKBINDINGPROC fUniformBlockBinding; + + // EXT_gpu_shader4 + typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint* params); + PFNGLGETVERTEXATTRIBIIVPROC fGetVertexAttribIiv; + typedef void (GLAPIENTRY * PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint* params); + PFNGLGETVERTEXATTRIBIUIVPROC fGetVertexAttribIuiv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); + PFNGLVERTEXATTRIBI4IPROC fVertexAttribI4i; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint* v); + PFNGLVERTEXATTRIBI4IVPROC fVertexAttribI4iv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + PFNGLVERTEXATTRIBI4UIPROC fVertexAttribI4ui; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint* v); + PFNGLVERTEXATTRIBI4UIVPROC fVertexAttribI4uiv; + typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* ptr); + PFNGLVERTEXATTRIBIPOINTERPROC fVertexAttribIPointer; + typedef void (GLAPIENTRY * PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); + PFNGLUNIFORM1UIPROC fUniform1ui; + typedef void (GLAPIENTRY * PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); + PFNGLUNIFORM2UIPROC fUniform2ui; + typedef void (GLAPIENTRY * PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); + PFNGLUNIFORM3UIPROC fUniform3ui; + typedef void (GLAPIENTRY * PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + PFNGLUNIFORM4UIPROC fUniform4ui; + typedef void (GLAPIENTRY * PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint* value); + PFNGLUNIFORM1UIVPROC fUniform1uiv; + typedef void (GLAPIENTRY * PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint* value); + PFNGLUNIFORM2UIVPROC fUniform2uiv; + typedef void (GLAPIENTRY * PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint* value); + PFNGLUNIFORM3UIVPROC fUniform3uiv; + typedef void (GLAPIENTRY * PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint* value); + PFNGLUNIFORM4UIVPROC fUniform4uiv; + typedef GLint (GLAPIENTRY * PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar* name); + PFNGLGETFRAGDATALOCATIONPROC fGetFragDataLocation; + + // 3D Textures + typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, + GLenum internalFormat, + GLenum width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, + const GLvoid* pixels); + PFNGLTEXIMAGE3DPROC fTexImage3D; + typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, GLenum format, + GLenum type, const GLvoid* pixels); + PFNGLTEXSUBIMAGE3DPROC fTexSubImage3D; + typedef void (GLAPIENTRY * PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, + GLint yoffset, GLint zoffset, GLint x, + GLint y, GLsizei width, GLsizei height); + PFNGLCOPYTEXSUBIMAGE3DPROC fCopyTexSubImage3D; + typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLsizei imageSize, const GLvoid* data); + PFNGLCOMPRESSEDTEXIMAGE3DPROC fCompressedTexImage3D; + typedef void (GLAPIENTRY * PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const GLvoid* data); + PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC fCompressedTexSubImage3D; + + // get_string_indexed + typedef const GLubyte* (GLAPIENTRY * PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); + PFNGLGETSTRINGIPROC fGetStringi; + + // APPLE_framebuffer_multisample + typedef void (GLAPIENTRY * PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE) (void); + PFNRESOLVEMULTISAMPLEFRAMEBUFFERAPPLE fResolveMultisampleFramebufferAPPLE; + + // NV_texture_barrier + typedef void (GLAPIENTRY * PFNTEXTUREBARRIERPROC) (void); + PFNTEXTUREBARRIERPROC fTextureBarrier; + + // NV_primitive_restart + void (GLAPIENTRY * fPrimitiveRestartIndex) (GLuint index); +}; + +} // namespace gl +} // namespace mozilla + +#endif /* GLCONTEXTSYMBOLS_H_ */ diff --git a/gfx/gl/GLContextTypes.cpp b/gfx/gl/GLContextTypes.cpp new file mode 100644 index 0000000000..2cca59dc96 --- /dev/null +++ b/gfx/gl/GLContextTypes.cpp @@ -0,0 +1,14 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 <cstring> + +using namespace mozilla::gl; + +GLFormats::GLFormats() +{ + std::memset(this, 0, sizeof(GLFormats)); +} diff --git a/gfx/gl/GLContextTypes.h b/gfx/gl/GLContextTypes.h new file mode 100644 index 0000000000..de59acf491 --- /dev/null +++ b/gfx/gl/GLContextTypes.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 GLCONTEXT_TYPES_H_ +#define GLCONTEXT_TYPES_H_ + +#include "GLTypes.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 +}; + +struct GLFormats +{ + // Constructs a zeroed object: + GLFormats(); + + GLenum color_texInternalFormat; + GLenum color_texFormat; + GLenum color_texType; + GLenum color_rbFormat; + + GLenum depthStencil; + GLenum depth; + GLenum stencil; + + GLsizei samples; +}; + +enum class CreateContextFlags : int8_t { + NONE = 0, + REQUIRE_COMPAT_PROFILE = 1 << 0, + // Force the use of hardware backed GL, don't allow software implementations. + FORCE_ENABLE_HARDWARE = 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, +}; +MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CreateContextFlags) + +} /* 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..9d270bf52d --- /dev/null +++ b/gfx/gl/GLContextWGL.h @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 : public GLContext +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextWGL, override) + // From Window: (possibly for offscreen!) + GLContextWGL(CreateContextFlags flags, + const SurfaceCaps& caps, + bool isOffscreen, + HDC aDC, + HGLRC aContext, + HWND aWindow = nullptr); + + // From PBuffer + GLContextWGL(CreateContextFlags flags, + const SurfaceCaps& caps, + bool isOffscreen, + HANDLE aPbuffer, + HDC aDC, + HGLRC aContext, + int aPixelFormat); + + ~GLContextWGL(); + + virtual GLContextType GetContextType() const override { return GLContextType::WGL; } + + static GLContextWGL* Cast(GLContext* gl) { + MOZ_ASSERT(gl->GetContextType() == GLContextType::WGL); + return static_cast<GLContextWGL*>(gl); + } + + bool Init() override; + + virtual bool MakeCurrentImpl(bool aForce) override; + + virtual bool IsCurrent() override; + + void SetIsDoubleBuffered(bool aIsDB); + + virtual bool IsDoubleBuffered() const override; + + virtual bool SupportsRobustness() const override; + + virtual bool SwapBuffers() override; + + virtual bool SetupLookupFunction() override; + + HGLRC Context() { return mContext; } + +protected: + friend class GLContextProviderWGL; + + HDC mDC; + HGLRC mContext; + HWND mWnd; + HANDLE mPBuffer; + int mPixelFormat; + bool mIsDoubleBuffered; +}; + +} +} + +#endif // GLCONTEXTWGL_H_ diff --git a/gfx/gl/GLDebugUtils.cpp b/gfx/gl/GLDebugUtils.cpp new file mode 100644 index 0000000000..cc8c611d4c --- /dev/null +++ b/gfx/gl/GLDebugUtils.cpp @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 "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..d828492526 --- /dev/null +++ b/gfx/gl/GLDebugUtils.h @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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 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..f580c06703 --- /dev/null +++ b/gfx/gl/GLDefs.h @@ -0,0 +1,88 @@ +/* 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" + +// 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 + +// EGL_KHR_fence_sync +#define LOCAL_EGL_SYNC_FENCE 0x30F9 +#define LOCAL_EGL_SYNC_TYPE 0x30F7 +#define LOCAL_EGL_SYNC_STATUS 0x30F1 +#define LOCAL_EGL_SYNC_CONDITION 0x30F8 +#define LOCAL_EGL_SIGNALED 0x30F2 +#define LOCAL_EGL_UNSIGNALED 0x30F3 +#define LOCAL_EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define LOCAL_EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define LOCAL_EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define LOCAL_EGL_TIMEOUT_EXPIRED 0x30F5 +#define LOCAL_EGL_CONDITION_SATISFIED 0x30F6 +#define LOCAL_EGL_SUCCESS 0x3000 + +// EGL_KHR_gl_texture_2D_image +#define LOCAL_EGL_GL_TEXTURE_2D 0x30B1 + +// EGL_KHR_image_base (not supplied by EGL_KHR_image!) +#define LOCAL_EGL_IMAGE_PRESERVED 0x30D2 + +// 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 + +// 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_direct3d_display +#define LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) +#define LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) + +// 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_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#define LOCAL_GL_CONTEXT_LOST 0x9242 +#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 + +#endif diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp new file mode 100644 index 0000000000..130bce1191 --- /dev/null +++ b/gfx/gl/GLLibraryEGL.cpp @@ -0,0 +1,797 @@ +/* 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 "angle/Platform.h" +#include "gfxConfig.h" +#include "gfxCrashReporterUtils.h" +#include "gfxUtils.h" +#include "mozilla/Preferences.h" +#include "mozilla/Assertions.h" +#include "mozilla/Telemetry.h" +#include "mozilla/Tokenizer.h" +#include "mozilla/ScopeExit.h" +#include "mozilla/Unused.h" +#include "nsDirectoryServiceDefs.h" +#include "nsDirectoryServiceUtils.h" +#include "nsIGfxInfo.h" +#include "nsPrintfCString.h" +#ifdef XP_WIN +#include "nsWindowsHelpers.h" +#endif +#include "OGLShaderProgram.h" +#include "prenv.h" +#include "GLContext.h" +#include "GLContextProvider.h" +#include "gfxPrefs.h" +#include "ScopedGLHelpers.h" + +namespace mozilla { +namespace gl { + +StaticMutex GLLibraryEGL::sMutex; +GLLibraryEGL sEGLLibrary; +#ifdef MOZ_B2G +MOZ_THREAD_LOCAL(EGLContext) GLLibraryEGL::sCurrentContext; +#endif + +// 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_KHR_lock_surface", + "EGL_ANGLE_surface_d3d_texture_2d_share_handle", + "EGL_EXT_create_context_robustness", + "EGL_KHR_image", + "EGL_KHR_fence_sync", + "EGL_ANDROID_native_fence_sync", + "EGL_ANDROID_image_crop", + "EGL_ANGLE_platform_angle", + "EGL_ANGLE_platform_angle_d3d" +}; + +#if defined(ANDROID) + +static PRLibrary* LoadApitraceLibrary() +{ + // Initialization of gfx prefs here is only needed during the unit tests... + gfxPrefs::GetSingleton(); + if (!gfxPrefs::UseApitrace()) { + return nullptr; + } + + static PRLibrary* sApitraceLibrary = nullptr; + + if (sApitraceLibrary) + return sApitraceLibrary; + + nsCString logFile = Preferences::GetCString("gfx.apitrace.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()); + + // 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", APITRACE_LIB); + + sApitraceLibrary = PR_LoadLibrary(APITRACE_LIB); + + return sApitraceLibrary; +} + +#endif // ANDROID + +#ifdef XP_WIN +// see the comment in GLLibraryEGL::EnsureInitialized() for the rationale here. +static PRLibrary* +LoadLibraryForEGLOnWindows(const nsAString& filename) +{ + nsCOMPtr<nsIFile> file; + nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(file)); + if (NS_FAILED(rv)) + return nullptr; + + file->Append(filename); + PRLibrary* lib = nullptr; + rv = file->Load(&lib); + if (NS_FAILED(rv)) { + nsPrintfCString msg("Failed to load %s - Expect EGL initialization to fail", + NS_LossyConvertUTF16toASCII(filename).get()); + NS_WARNING(msg.get()); + } + return lib; +} + +#endif // XP_WIN + +static EGLDisplay +GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType) +{ + EGLint attrib_list[] = { LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, + // Requires: + LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE, + LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + LOCAL_EGL_NONE }; + EGLDisplay display = egl.fGetPlatformDisplayEXT(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 EGL_NO_DISPLAY; + } + + if (!egl.fInitialize(display, nullptr, nullptr)) + return EGL_NO_DISPLAY; + + return display; +} + +static bool +IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo, + nsACString* const out_failureId) +{ + int32_t angleSupport; + nsCString failureId; + gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, + nsIGfxInfo::FEATURE_WEBGL_ANGLE, + failureId, + &angleSupport); + if (failureId.IsEmpty() && angleSupport != nsIGfxInfo::FEATURE_STATUS_OK) { + // This shouldn't happen, if we see this it's because we've missed + // some failure paths + failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_NOT_OK"); + } + if (out_failureId->IsEmpty()) { + *out_failureId = failureId; + } + return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK); +} + +static EGLDisplay +GetAndInitDisplay(GLLibraryEGL& egl, void* displayType) +{ + EGLDisplay display = egl.fGetDisplay(displayType); + if (display == EGL_NO_DISPLAY) + return EGL_NO_DISPLAY; + + if (!egl.fInitialize(display, nullptr, nullptr)) + return EGL_NO_DISPLAY; + + return display; +} + +class AngleErrorReporting: public angle::Platform { +public: + AngleErrorReporting() + { + // No static constructor + } + + void SetFailureId(nsACString* const aFailureId) + { + mFailureId = aFailureId; + } + + void logError(const char *errorMessage) override + { + 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("%i", intToken.AsInteger()); + } else { + *mFailureId = "FAILURE_ID_ANGLE_UNKNOWN"; + } + } +private: + nsACString* mFailureId; +}; + +AngleErrorReporting gAngleErrorReporter; + +static EGLDisplay +GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl, nsACString* const out_failureId) +{ + EGLDisplay ret = 0; + + FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE); + + if (!gfxPrefs::WebGLANGLETryD3D11()) + d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref", + NS_LITERAL_CSTRING("FAILURE_ID_ANGLE_PREF")); + + if (gfxPrefs::WebGLANGLEForceD3D11()) + d3d11ANGLE.UserForceEnable("User force-enabled D3D11 ANGLE on disabled hardware"); + + gAngleErrorReporter.SetFailureId(out_failureId); + egl.fANGLEPlatformInitialize(&gAngleErrorReporter); + + 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 (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE)) { + return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE); + } + + if (d3d11ANGLE.IsEnabled()) { + ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE); + } + + if (!ret) { + ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY); + } + + if (!ret && out_failureId->IsEmpty()) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_NO_DISP"); + } + + return ret; +} + +bool +GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface) +{ + StaticMutexAutoUnlock lock(sMutex); + if (!mReadbackGL) { + nsCString discardFailureId; + mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE, + &discardFailureId); + } + + ScopedTexture destTex(mReadbackGL); + const GLuint target = mReadbackGL->GetPreferredEGLImageTextureTarget(); + ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target); + mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST); + mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST); + mReadbackGL->fEGLImageTargetTexture2D(target, image); + + ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(target, + out_surface->GetFormat()); + int shaderConfig = config.mFeatures; + mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target, + out_surface->GetSize(), shaderConfig); + + return true; +} + +bool +GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId) +{ + if (mInitialized) { + return true; + } + + mozilla::ScopedGfxFeatureReporter reporter("EGL"); + +#ifdef MOZ_B2G + if (!sCurrentContext.init()) + MOZ_CRASH("GFX: Tls init failed"); +#endif + +#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. + // Try it first. Note that _46 will never be in the system + // directory and we ship with at least _43. So there is no point + // trying _46 and _43 in the system directory. + + if (LoadLibrarySystem32(L"d3dcompiler_47.dll")) + break; + +#ifdef MOZ_D3DCOMPILER_VISTA_DLL + if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_VISTA_DLL)))) + break; +#endif + +#ifdef MOZ_D3DCOMPILER_XP_DLL + if (LoadLibraryForEGLOnWindows(NS_LITERAL_STRING(NS_STRINGIFY(MOZ_D3DCOMPILER_XP_DLL)))) + break; +#endif + + MOZ_ASSERT(false, "d3dcompiler DLL loading failed."); + } while (false); + + LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libGLESv2.dll")); + + mEGLLibrary = LoadLibraryForEGLOnWindows(NS_LITERAL_STRING("libEGL.dll")); + + if (!mEGLLibrary) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_LOAD"); + return false; + } + } + +#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) { + printf_stderr("Attempting load of libEGL.so\n"); + mEGLLibrary = PR_LoadLibrary("libEGL.so"); + } +#if defined(XP_UNIX) + if (!mEGLLibrary) { + mEGLLibrary = PR_LoadLibrary("libEGL.so.1"); + } +#endif + + if (!mEGLLibrary) { + NS_WARNING("Couldn't load EGL LIB."); + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_LOAD_2"); + return false; + } + +#endif // !Windows + +#define SYMBOL(name) \ +{ (PRFuncPtr*) &mSymbols.f##name, { "egl" #name, nullptr } } + + GLLibraryLoader::SymLoadStruct earlySymbols[] = { + SYMBOL(GetDisplay), + SYMBOL(Terminate), + SYMBOL(GetCurrentSurface), + SYMBOL(GetCurrentContext), + SYMBOL(MakeCurrent), + SYMBOL(DestroyContext), + SYMBOL(CreateContext), + SYMBOL(DestroySurface), + SYMBOL(CreateWindowSurface), + SYMBOL(CreatePbufferSurface), + 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(QuerySurface), + { nullptr, { nullptr } } + }; + + if (!GLLibraryLoader::LoadSymbols(mEGLLibrary, &earlySymbols[0])) { + NS_WARNING("Couldn't find required entry points in EGL library (early init)"); + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_SYM"); + return false; + } + + GLLibraryLoader::SymLoadStruct optionalSymbols[] = { + // On Android 4.3 and up, certain features like ANDROID_native_fence_sync + // can only be queried by using a special eglQueryString. + { (PRFuncPtr*) &mSymbols.fQueryStringImplementationANDROID, + { "_Z35eglQueryStringImplementationANDROIDPvi", nullptr } }, + { nullptr, { nullptr } } + }; + + // Do not warn about the failure to load this - see bug 1092191 + Unused << GLLibraryLoader::LoadSymbols(mEGLLibrary, &optionalSymbols[0], + nullptr, nullptr, false); + + InitClientExtensions(); + + const auto lookupFunction = + (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress; + + // Client exts are ready. (But not display exts!) + if (IsExtensionSupported(ANGLE_platform_angle_d3d)) { + GLLibraryLoader::SymLoadStruct d3dSymbols[] = { + { (PRFuncPtr*)&mSymbols.fANGLEPlatformInitialize, { "ANGLEPlatformInitialize", nullptr } }, + { (PRFuncPtr*)&mSymbols.fANGLEPlatformShutdown, { "ANGLEPlatformShutdown", nullptr } }, + { (PRFuncPtr*)&mSymbols.fGetPlatformDisplayEXT, { "eglGetPlatformDisplayEXT", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &d3dSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports ANGLE_platform_angle_d3d without exposing its functions!"); + + MarkExtensionUnsupported(ANGLE_platform_angle_d3d); + + mSymbols.fGetPlatformDisplayEXT = nullptr; + } + } + + // Check the ANGLE support the system has + nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); + mIsANGLE = IsExtensionSupported(ANGLE_platform_angle); + + EGLDisplay chosenDisplay = nullptr; + + if (IsExtensionSupported(ANGLE_platform_angle_d3d)) { + nsCString accelAngleFailureId; + bool accelAngleSupport = IsAccelAngleSupported(gfxInfo, &accelAngleFailureId); + bool shouldTryAccel = forceAccel || accelAngleSupport; + bool shouldTryWARP = !forceAccel; // Only if ANGLE not supported or fails + + // If WARP preferred, will override ANGLE support + if (gfxPrefs::WebGLANGLEForceWARP()) { + shouldTryWARP = true; + shouldTryAccel = false; + if (accelAngleFailureId.IsEmpty()) { + accelAngleFailureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_FORCE_WARP"); + } + } + + // Hardware accelerated ANGLE path (supported or force accel) + if (shouldTryAccel) { + chosenDisplay = GetAndInitDisplayForAccelANGLE(*this, out_failureId); + } + + // Report the acceleration status to telemetry + if (!chosenDisplay) { + if (accelAngleFailureId.IsEmpty()) { + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID, + NS_LITERAL_CSTRING("FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN")); + } else { + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID, + accelAngleFailureId); + } + } else { + Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID, + NS_LITERAL_CSTRING("SUCCESS")); + } + + // Fallback to a WARP display if ANGLE fails, or if WARP is forced + if (!chosenDisplay && shouldTryWARP) { + chosenDisplay = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY); + if (!chosenDisplay) { + if (out_failureId->IsEmpty()) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WARP_FALLBACK"); + } + NS_ERROR("Fallback WARP context failed to initialize."); + return false; + } + mIsWARP = true; + } + } else { + chosenDisplay = GetAndInitDisplay(*this, EGL_DEFAULT_DISPLAY); + } + + if (!chosenDisplay) { + if (out_failureId->IsEmpty()) { + *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_DISPLAY"); + } + NS_WARNING("Failed to initialize a display."); + return false; + } + mEGLDisplay = chosenDisplay; + + InitDisplayExtensions(); + + //////////////////////////////////// + // Alright, load display exts. + + if (IsExtensionSupported(KHR_lock_surface)) { + GLLibraryLoader::SymLoadStruct lockSymbols[] = { + { (PRFuncPtr*) &mSymbols.fLockSurface, { "eglLockSurfaceKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fUnlockSurface, { "eglUnlockSurfaceKHR", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &lockSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!"); + + MarkExtensionUnsupported(KHR_lock_surface); + + mSymbols.fLockSurface = nullptr; + mSymbols.fUnlockSurface = nullptr; + } + } + + if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) { + GLLibraryLoader::SymLoadStruct d3dSymbols[] = { + { (PRFuncPtr*) &mSymbols.fQuerySurfacePointerANGLE, { "eglQuerySurfacePointerANGLE", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &d3dSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports ANGLE_surface_d3d_texture_2d_share_handle without exposing its functions!"); + + MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle); + + mSymbols.fQuerySurfacePointerANGLE = nullptr; + } + } + + if (IsExtensionSupported(KHR_fence_sync)) { + GLLibraryLoader::SymLoadStruct syncSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCreateSync, { "eglCreateSyncKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDestroySync, { "eglDestroySyncKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fClientWaitSync, { "eglClientWaitSyncKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fGetSyncAttrib, { "eglGetSyncAttribKHR", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &syncSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!"); + + MarkExtensionUnsupported(KHR_fence_sync); + + mSymbols.fCreateSync = nullptr; + mSymbols.fDestroySync = nullptr; + mSymbols.fClientWaitSync = nullptr; + mSymbols.fGetSyncAttrib = nullptr; + } + } + + if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) { + GLLibraryLoader::SymLoadStruct imageSymbols[] = { + { (PRFuncPtr*) &mSymbols.fCreateImage, { "eglCreateImageKHR", nullptr } }, + { (PRFuncPtr*) &mSymbols.fDestroyImage, { "eglDestroyImageKHR", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &imageSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!"); + + MarkExtensionUnsupported(KHR_image); + MarkExtensionUnsupported(KHR_image_base); + MarkExtensionUnsupported(KHR_image_pixmap); + + mSymbols.fCreateImage = nullptr; + mSymbols.fDestroyImage = nullptr; + } + } else { + MarkExtensionUnsupported(KHR_image_pixmap); + } + + if (IsExtensionSupported(ANDROID_native_fence_sync)) { + GLLibraryLoader::SymLoadStruct nativeFenceSymbols[] = { + { (PRFuncPtr*) &mSymbols.fDupNativeFenceFDANDROID, { "eglDupNativeFenceFDANDROID", nullptr } }, + { nullptr, { nullptr } } + }; + + bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary, + &nativeFenceSymbols[0], + lookupFunction); + if (!success) { + NS_ERROR("EGL supports ANDROID_native_fence_sync without exposing its functions!"); + + MarkExtensionUnsupported(ANDROID_native_fence_sync); + + mSymbols.fDupNativeFenceFDANDROID = nullptr; + } + } + + mInitialized = true; + reporter.SetSuccessful(); + return true; +} + +template<size_t N> +static void +MarkExtensions(const char* rawExtString, bool shouldDumpExts, const char* extType, + 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, sEGLExtensionNames, out); +} + +void +GLLibraryEGL::InitClientExtensions() +{ + 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 client extensions.\n"); + } + return; + } + + MarkExtensions(rawExtString, shouldDumpExts, "client", &mAvailableExtensions); +} + +void +GLLibraryEGL::InitDisplayExtensions() +{ + MOZ_ASSERT(mEGLDisplay); + + const bool shouldDumpExts = GLContext::ShouldDumpExts(); + + const auto rawExtString = (const char*)fQueryString(mEGLDisplay, + LOCAL_EGL_EXTENSIONS); + if (!rawExtString) { + NS_WARNING("Failed to query EGL display extensions!."); + return; + } + + MarkExtensions(rawExtString, shouldDumpExts, "display", &mAvailableExtensions); +} + +void +GLLibraryEGL::DumpEGLConfig(EGLConfig cfg) +{ + int attrval; + int err; + +#define ATTR(_x) do { \ + fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \ + if ((err = fGetError()) != 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 +GLLibraryEGL::DumpEGLConfigs() +{ + int nc = 0; + fGetConfigs(mEGLDisplay, nullptr, 0, &nc); + EGLConfig* ec = new EGLConfig[nc]; + fGetConfigs(mEGLDisplay, ec, nc, &nc); + + for (int i = 0; i < nc; ++i) { + printf_stderr("========= EGL Config %d ========\n", i); + DumpEGLConfig(ec[i]); + } + + delete [] ec; +} + +#ifdef DEBUG +static bool +ShouldTrace() +{ + static bool ret = gfxEnv::GlDebugVerbose(); + return ret; +} + +/*static*/ void +GLLibraryEGL::BeforeGLCall(const char* glFunction) +{ + if (ShouldTrace()) { + printf_stderr("[egl] > %s\n", glFunction); + } +} + +/*static*/ void +GLLibraryEGL::AfterGLCall(const char* glFunction) +{ + if (ShouldTrace()) { + printf_stderr("[egl] < %s\n", glFunction); + } +} +#endif + +} /* namespace gl */ +} /* namespace mozilla */ + diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h new file mode 100644 index 0000000000..fa6ea748b6 --- /dev/null +++ b/gfx/gl/GLLibraryEGL.h @@ -0,0 +1,704 @@ +/* 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 "GLLibraryLoader.h" +#include "mozilla/StaticMutex.h" +#include "mozilla/ThreadLocal.h" +#include "nsIFile.h" +#include "GeckoProfiler.h" + +#include <bitset> +#include <vector> + +#ifdef XP_WIN + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif + + #include <windows.h> + + typedef HDC EGLNativeDisplayType; + typedef HBITMAP EGLNativePixmapType; + typedef HWND EGLNativeWindowType; +#else + typedef void* EGLNativeDisplayType; + typedef void* EGLNativePixmapType; + typedef void* EGLNativeWindowType; + + #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 + // + // This should really go in GLLibraryEGL.cpp but we currently reference + // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring + // will come in subsequent patches on Bug 732865 + #define APITRACE_LIB "/data/local/tmp/egltrace.so" + #endif +#endif + +#if defined(MOZ_X11) +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay()) +#else +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#endif + +namespace angle { +class Platform; +} + +namespace mozilla { + +namespace gfx { +class DataSourceSurface; +} + +namespace gl { + +#undef BEFORE_GL_CALL +#undef AFTER_GL_CALL + +#ifdef DEBUG + +#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 BEFORE_GL_CALL \ + PROFILER_LABEL_FUNC( \ + js::ProfileEntry::Category::GRAPHICS);\ + BeforeGLCall(MOZ_FUNCTION_NAME) +#else +#define BEFORE_GL_CALL do { \ + BeforeGLCall(MOZ_FUNCTION_NAME); \ +} while (0) +#endif + +#define AFTER_GL_CALL do { \ + AfterGLCall(MOZ_FUNCTION_NAME); \ +} while (0) +#else +#ifdef MOZ_WIDGET_ANDROID +// Record the name of the GL call for better hang stacks on Android. +#define BEFORE_GL_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS) +#else +#define BEFORE_GL_CALL +#endif +#define AFTER_GL_CALL +#endif + +class GLContext; + +class GLLibraryEGL +{ +public: + GLLibraryEGL() + : mInitialized(false), + mEGLLibrary(nullptr), + mEGLDisplay(EGL_NO_DISPLAY), + mIsANGLE(false), + mIsWARP(false) + { + ClearSymbols(); + } + + void ClearSymbols() { + mSymbols.fANGLEPlatformInitialize = nullptr; + mSymbols.fANGLEPlatformShutdown = nullptr; + mSymbols.fGetDisplay = nullptr; + mSymbols.fGetPlatformDisplayEXT = nullptr; + mSymbols.fTerminate = nullptr; + mSymbols.fGetCurrentSurface = nullptr; + mSymbols.fGetCurrentContext = nullptr; + mSymbols.fMakeCurrent = nullptr; + mSymbols.fDestroyContext = nullptr; + mSymbols.fCreateContext = nullptr; + mSymbols.fDestroySurface = nullptr; + mSymbols.fCreateWindowSurface = nullptr; + mSymbols.fCreatePbufferSurface = nullptr; + mSymbols.fCreatePixmapSurface = nullptr; + mSymbols.fBindAPI = nullptr; + mSymbols.fInitialize = nullptr; + mSymbols.fChooseConfig = nullptr; + mSymbols.fGetError = nullptr; + mSymbols.fGetConfigAttrib = nullptr; + mSymbols.fGetConfigs = nullptr; + mSymbols.fWaitNative = nullptr; + mSymbols.fGetProcAddress = nullptr; + mSymbols.fSwapBuffers = nullptr; + mSymbols.fCopyBuffers = nullptr; + mSymbols.fQueryString = nullptr; + mSymbols.fQueryStringImplementationANDROID = nullptr; + mSymbols.fQueryContext = nullptr; + mSymbols.fBindTexImage = nullptr; + mSymbols.fReleaseTexImage = nullptr; + mSymbols.fCreateImage = nullptr; + mSymbols.fDestroyImage = nullptr; + mSymbols.fLockSurface = nullptr; + mSymbols.fUnlockSurface = nullptr; + mSymbols.fQuerySurface = nullptr; + mSymbols.fQuerySurfacePointerANGLE = nullptr; + mSymbols.fCreateSync = nullptr; + mSymbols.fDestroySync = nullptr; + mSymbols.fClientWaitSync = nullptr; + mSymbols.fGetSyncAttrib = nullptr; + mSymbols.fDupNativeFenceFDANDROID = nullptr; + } + + void InitClientExtensions(); + void InitDisplayExtensions(); + + /** + * 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 EGLExtensions { + KHR_image_base, + KHR_image_pixmap, + KHR_gl_texture_2D_image, + KHR_lock_surface, + ANGLE_surface_d3d_texture_2d_share_handle, + EXT_create_context_robustness, + KHR_image, + KHR_fence_sync, + ANDROID_native_fence_sync, + EGL_ANDROID_image_crop, + ANGLE_platform_angle, + ANGLE_platform_angle_d3d, + Extensions_Max + }; + + bool IsExtensionSupported(EGLExtensions aKnownExtension) const { + return mAvailableExtensions[aKnownExtension]; + } + + void MarkExtensionUnsupported(EGLExtensions aKnownExtension) { + mAvailableExtensions[aKnownExtension] = false; + } + +protected: + std::bitset<Extensions_Max> mAvailableExtensions; + +public: + + EGLDisplay fGetDisplay(void* display_id) + { + BEFORE_GL_CALL; + EGLDisplay disp = mSymbols.fGetDisplay(display_id); + AFTER_GL_CALL; + return disp; + } + + EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLDisplay disp = mSymbols.fGetPlatformDisplayEXT(platform, native_display, attrib_list); + AFTER_GL_CALL; + return disp; + } + + EGLBoolean fTerminate(EGLDisplay display) + { + BEFORE_GL_CALL; + EGLBoolean ret = mSymbols.fTerminate(display); + AFTER_GL_CALL; + return ret; + } + + EGLSurface fGetCurrentSurface(EGLint id) + { + BEFORE_GL_CALL; + EGLSurface surf = mSymbols.fGetCurrentSurface(id); + AFTER_GL_CALL; + return surf; + } + + EGLContext fGetCurrentContext() + { + BEFORE_GL_CALL; + EGLContext context = mSymbols.fGetCurrentContext(); + AFTER_GL_CALL; + return context; + } + + EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fMakeCurrent(dpy, draw, read, ctx); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fDestroyContext(dpy, ctx); + AFTER_GL_CALL; + return b; + } + + EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLContext ctx = mSymbols.fCreateContext(dpy, config, share_context, attrib_list); + AFTER_GL_CALL; + return ctx; + } + + EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fDestroySurface(dpy, surface); + AFTER_GL_CALL; + return b; + } + + EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLSurface surf = mSymbols.fCreateWindowSurface(dpy, config, win, attrib_list); + AFTER_GL_CALL; + return surf; + } + + EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLSurface surf = mSymbols.fCreatePbufferSurface(dpy, config, attrib_list); + AFTER_GL_CALL; + return surf; + } + + EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLSurface surf = mSymbols.fCreatePixmapSurface(dpy, config, pixmap, attrib_list); + AFTER_GL_CALL; + return surf; + } + + EGLBoolean fBindAPI(EGLenum api) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fBindAPI(api); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fInitialize(dpy, major, minor); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fChooseConfig(dpy, attrib_list, configs, config_size, num_config); + AFTER_GL_CALL; + return b; + } + + EGLint fGetError() + { + BEFORE_GL_CALL; + EGLint i = mSymbols.fGetError(); + AFTER_GL_CALL; + return i; + } + + EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fGetConfigAttrib(dpy, config, attribute, value); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fGetConfigs(dpy, configs, config_size, num_config); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fWaitNative(EGLint engine) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fWaitNative(engine); + AFTER_GL_CALL; + return b; + } + + EGLCastToRelevantPtr fGetProcAddress(const char* procname) + { + BEFORE_GL_CALL; + EGLCastToRelevantPtr p = mSymbols.fGetProcAddress(procname); + AFTER_GL_CALL; + return p; + } + + EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fSwapBuffers(dpy, surface); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fCopyBuffers(dpy, surface, target); + AFTER_GL_CALL; + return b; + } + + const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) + { + BEFORE_GL_CALL; + const GLubyte* b; + if (mSymbols.fQueryStringImplementationANDROID) { + b = mSymbols.fQueryStringImplementationANDROID(dpy, name); + } else { + b = mSymbols.fQueryString(dpy, name); + } + AFTER_GL_CALL; + return b; + } + + EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fQueryContext(dpy, ctx, attribute, value); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fBindTexImage(dpy, surface, buffer); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fReleaseTexImage(dpy, surface, buffer); + AFTER_GL_CALL; + return b; + } + + EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLImage i = mSymbols.fCreateImage(dpy, ctx, target, buffer, attrib_list); + AFTER_GL_CALL; + return i; + } + + EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fDestroyImage(dpy, image); + AFTER_GL_CALL; + return b; + } + + // New extension which allow us to lock texture and get raw image pointer + EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fLockSurface(dpy, surface, attrib_list); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fUnlockSurface(EGLDisplay dpy, EGLSurface surface) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fUnlockSurface(dpy, surface); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fQuerySurface(dpy, surface, attribute, value); + AFTER_GL_CALL; + return b; + } + + EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fQuerySurfacePointerANGLE(dpy, surface, attribute, value); + AFTER_GL_CALL; + return b; + } + + EGLSync fCreateSync(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) + { + BEFORE_GL_CALL; + EGLSync ret = mSymbols.fCreateSync(dpy, type, attrib_list); + AFTER_GL_CALL; + return ret; + } + + EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fDestroySync(dpy, sync); + AFTER_GL_CALL; + return b; + } + + EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) + { + BEFORE_GL_CALL; + EGLint ret = mSymbols.fClientWaitSync(dpy, sync, flags, timeout); + AFTER_GL_CALL; + return ret; + } + + EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value) + { + BEFORE_GL_CALL; + EGLBoolean b = mSymbols.fGetSyncAttrib(dpy, sync, attribute, value); + AFTER_GL_CALL; + return b; + } + + EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) + { + MOZ_ASSERT(mSymbols.fDupNativeFenceFDANDROID); + BEFORE_GL_CALL; + EGLint ret = mSymbols.fDupNativeFenceFDANDROID(dpy, sync); + AFTER_GL_CALL; + return ret; + } + + void fANGLEPlatformInitialize(angle::Platform* platform) + { + MOZ_ASSERT(mSymbols.fANGLEPlatformInitialize); + BEFORE_GL_CALL; + mSymbols.fANGLEPlatformInitialize(platform); + AFTER_GL_CALL; + } + + void fANGLEPlatformShutdown() + { + MOZ_ASSERT(mSymbols.fANGLEPlatformShutdown); + BEFORE_GL_CALL; + mSymbols.fANGLEPlatformShutdown(); + AFTER_GL_CALL; + } + + EGLDisplay Display() { + MOZ_ASSERT(mInitialized); + return mEGLDisplay; + } + + bool IsANGLE() const { + MOZ_ASSERT(mInitialized); + return mIsANGLE; + } + + bool IsWARP() const { + MOZ_ASSERT(mInitialized); + return mIsWARP; + } + + bool HasKHRImageBase() { + return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base); + } + + bool HasKHRImagePixmap() { + return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_pixmap); + } + + bool HasKHRImageTexture2D() { + return IsExtensionSupported(KHR_gl_texture_2D_image); + } + + bool HasANGLESurfaceD3DTexture2DShareHandle() { + return IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle); + } + + bool HasRobustness() const { + return IsExtensionSupported(EXT_create_context_robustness); + } + + bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface); + + bool EnsureInitialized(bool forceAccel, nsACString* const out_failureId); + + void DumpEGLConfig(EGLConfig cfg); + void DumpEGLConfigs(); + + struct { + typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void* display_id); + pfnGetDisplay fGetDisplay; + typedef EGLDisplay(GLAPIENTRY * pfnGetPlatformDisplayEXT)(EGLenum platform, void* native_display, const EGLint* attrib_list); + pfnGetPlatformDisplayEXT fGetPlatformDisplayEXT; + typedef EGLBoolean (GLAPIENTRY * pfnTerminate)(EGLDisplay dpy); + pfnTerminate fTerminate; + typedef EGLSurface (GLAPIENTRY * pfnGetCurrentSurface)(EGLint); + pfnGetCurrentSurface fGetCurrentSurface; + typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void); + pfnGetCurrentContext fGetCurrentContext; + typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); + pfnMakeCurrent fMakeCurrent; + typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx); + pfnDestroyContext fDestroyContext; + typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list); + pfnCreateContext fCreateContext; + typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface); + pfnDestroySurface fDestroySurface; + typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list); + pfnCreateWindowSurface fCreateWindowSurface; + typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list); + pfnCreatePbufferSurface fCreatePbufferSurface; + typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list); + pfnCreatePixmapSurface fCreatePixmapSurface; + typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api); + pfnBindAPI fBindAPI; + typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor); + pfnInitialize fInitialize; + typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config); + pfnChooseConfig fChooseConfig; + typedef EGLint (GLAPIENTRY * pfnGetError)(void); + pfnGetError fGetError; + typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value); + pfnGetConfigAttrib fGetConfigAttrib; + typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config); + pfnGetConfigs fGetConfigs; + typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine); + pfnWaitNative fWaitNative; + typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char* procname); + pfnGetProcAddress fGetProcAddress; + typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface); + pfnSwapBuffers fSwapBuffers; + typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface, + EGLNativePixmapType target); + pfnCopyBuffers fCopyBuffers; + typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name); + pfnQueryString fQueryString; + pfnQueryString fQueryStringImplementationANDROID; + typedef EGLBoolean (GLAPIENTRY * pfnQueryContext)(EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint* value); + pfnQueryContext fQueryContext; + typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); + pfnBindTexImage fBindTexImage; + typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer); + pfnReleaseTexImage fReleaseTexImage; + typedef EGLImage (GLAPIENTRY * pfnCreateImage)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list); + pfnCreateImage fCreateImage; + typedef EGLBoolean (GLAPIENTRY * pfnDestroyImage)(EGLDisplay dpy, EGLImage image); + pfnDestroyImage fDestroyImage; + + // New extension which allow us to lock texture and get raw image pointer + typedef EGLBoolean (GLAPIENTRY * pfnLockSurface)(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list); + pfnLockSurface fLockSurface; + typedef EGLBoolean (GLAPIENTRY * pfnUnlockSurface)(EGLDisplay dpy, EGLSurface surface); + pfnUnlockSurface fUnlockSurface; + typedef EGLBoolean (GLAPIENTRY * pfnQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value); + pfnQuerySurface fQuerySurface; + + typedef EGLBoolean (GLAPIENTRY * pfnQuerySurfacePointerANGLE)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value); + pfnQuerySurfacePointerANGLE fQuerySurfacePointerANGLE; + + typedef EGLSync (GLAPIENTRY * pfnCreateSync)(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list); + pfnCreateSync fCreateSync; + typedef EGLBoolean (GLAPIENTRY * pfnDestroySync)(EGLDisplay dpy, EGLSync sync); + pfnDestroySync fDestroySync; + typedef EGLint (GLAPIENTRY * pfnClientWaitSync)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); + pfnClientWaitSync fClientWaitSync; + typedef EGLBoolean (GLAPIENTRY * pfnGetSyncAttrib)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value); + pfnGetSyncAttrib fGetSyncAttrib; + typedef EGLint (GLAPIENTRY * pfnDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync); + pfnDupNativeFenceFDANDROID fDupNativeFenceFDANDROID; + + typedef void (GLAPIENTRY * pfnANGLEPlatformInitialize)(angle::Platform* platform); + pfnANGLEPlatformInitialize fANGLEPlatformInitialize; + typedef void (GLAPIENTRY * pfnANGLEPlatformShutdown)(); + pfnANGLEPlatformShutdown fANGLEPlatformShutdown; + } mSymbols; + +#ifdef DEBUG + static void BeforeGLCall(const char* glFunction); + static void AfterGLCall(const char* glFunction); +#endif + +#ifdef MOZ_B2G + EGLContext CachedCurrentContext() { + return sCurrentContext.get(); + } + void UnsetCachedCurrentContext() { + sCurrentContext.set(nullptr); + } + void SetCachedCurrentContext(EGLContext aCtx) { + sCurrentContext.set(aCtx); + } + bool CachedCurrentContextMatches() { + return sCurrentContext.get() == fGetCurrentContext(); + } + +private: + static MOZ_THREAD_LOCAL(EGLContext) sCurrentContext; +public: + +#else + EGLContext CachedCurrentContext() { + return nullptr; + } + void UnsetCachedCurrentContext() {} + void SetCachedCurrentContext(EGLContext aCtx) { } + bool CachedCurrentContextMatches() { return true; } +#endif + +private: + bool mInitialized; + PRLibrary* mEGLLibrary; + EGLDisplay mEGLDisplay; + RefPtr<GLContext> mReadbackGL; + + bool mIsANGLE; + bool mIsWARP; + static StaticMutex sMutex; +}; + +extern GLLibraryEGL sEGLLibrary; +#define EGL_DISPLAY() sEGLLibrary.Display() + +} /* 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..801ffe37cd --- /dev/null +++ b/gfx/gl/GLLibraryLoader.cpp @@ -0,0 +1,117 @@ +/* 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 "nsDebug.h" + +#ifdef WIN32 +#include <windows.h> +#endif + +namespace mozilla { +namespace gl { + +bool +GLLibraryLoader::OpenLibrary(const char* library) +{ + PRLibSpec lspec; + lspec.type = PR_LibSpec_Pathname; + lspec.value.pathname = library; + + mLibrary = PR_LoadLibraryWithFlags(lspec, PR_LD_LAZY | PR_LD_LOCAL); + if (!mLibrary) + return false; + + return true; +} + +bool +GLLibraryLoader::LoadSymbols(const SymLoadStruct* firstStruct, + bool tryplatform, + const char* prefix, + bool warnOnFailure) +{ + return LoadSymbols(mLibrary, + firstStruct, + tryplatform ? mLookupFunc : nullptr, + prefix, + warnOnFailure); +} + +PRFuncPtr +GLLibraryLoader::LookupSymbol(PRLibrary* lib, + const char* sym, + PlatformLookupFunction lookupFunction) +{ + PRFuncPtr res = 0; + + // try finding it in the library directly, if we have one + if (lib) { + res = PR_FindFunctionSymbol(lib, sym); + } + + // then try looking it up via the lookup symbol + if (!res && lookupFunction) { + res = lookupFunction(sym); + } + + // finally just try finding it in the process + if (!res) { + PRLibrary* leakedLibRef; + res = PR_FindFunctionSymbolAndLibrary(sym, &leakedLibRef); + } + + return res; +} + +bool +GLLibraryLoader::LoadSymbols(PRLibrary* lib, + const SymLoadStruct* firstStruct, + PlatformLookupFunction lookupFunction, + const char* prefix, + bool warnOnFailure) +{ + char sbuf[MAX_SYMBOL_LENGTH * 2]; + int failCount = 0; + + const SymLoadStruct* ss = firstStruct; + while (ss->symPointer) { + *ss->symPointer = 0; + + for (int i = 0; i < MAX_SYMBOL_NAMES; i++) { + if (ss->symNames[i] == nullptr) + break; + + const char* s = ss->symNames[i]; + if (prefix && *prefix != 0) { + strcpy(sbuf, prefix); + strcat(sbuf, ss->symNames[i]); + s = sbuf; + } + + PRFuncPtr p = LookupSymbol(lib, s, lookupFunction); + if (p) { + *ss->symPointer = p; + break; + } + } + + if (*ss->symPointer == 0) { + if (warnOnFailure) { + printf_stderr("Can't find symbol '%s'.\n", ss->symNames[0]); + } + + failCount++; + } + + ss++; + } + + return failCount == 0 ? true : false; +} + +} /* namespace gl */ +} /* namespace mozilla */ + diff --git a/gfx/gl/GLLibraryLoader.h b/gfx/gl/GLLibraryLoader.h new file mode 100644 index 0000000000..70ba43c4db --- /dev/null +++ b/gfx/gl/GLLibraryLoader.h @@ -0,0 +1,63 @@ +/* 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 <stdio.h> + +#include "GLDefs.h" +#include "nscore.h" +#include "prlink.h" + +namespace mozilla { +namespace gl { + +class GLLibraryLoader +{ +public: + bool OpenLibrary(const char* library); + + typedef PRFuncPtr (GLAPIENTRY * PlatformLookupFunction) (const char*); + + enum { + MAX_SYMBOL_NAMES = 6, + MAX_SYMBOL_LENGTH = 128 + }; + + typedef struct { + PRFuncPtr* symPointer; + const char* symNames[MAX_SYMBOL_NAMES]; + } SymLoadStruct; + + bool LoadSymbols(const SymLoadStruct* firstStruct, + bool tryplatform = false, + const char* prefix = nullptr, + bool warnOnFailure = true); + + /* + * Static version of the functions in this class + */ + static PRFuncPtr LookupSymbol(PRLibrary* lib, + const char* symname, + PlatformLookupFunction lookupFunction = nullptr); + static bool LoadSymbols(PRLibrary* lib, + const SymLoadStruct* firstStruct, + PlatformLookupFunction lookupFunction = nullptr, + const char* prefix = nullptr, + bool warnOnFailure = true); +protected: + GLLibraryLoader() { + mLibrary = nullptr; + mLookupFunc = nullptr; + } + + PRLibrary* mLibrary; + PlatformLookupFunction mLookupFunc; +}; + +} /* namespace gl */ +} /* namespace mozilla */ + +#endif /* GLLIBRARYLOADER_H_ */ diff --git a/gfx/gl/GLParseRegistryXML.py b/gfx/gl/GLParseRegistryXML.py new file mode 100755 index 0000000000..60daca6e56 --- /dev/null +++ b/gfx/gl/GLParseRegistryXML.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python +# coding=utf8 + + +################################################################################ +# TUTORIAL +# This script will generate GLConsts.h +# +# Step 1: +# Download the last gl.xml, egl.xml, glx.xml and wgl.xml from +# http://www.opengl.org/registry/#specfiles into a directory of your choice +# +# Step 2: +# Execute this script ./GLParseRegistryXML.py [your dir containing XML files] +# +# Step 3: +# Do not add the downloaded XML in the patch +# +# Step 4: +# Enjoy =) +# +################################################################################ + +# includes +import os +import sys +import xml.etree.ElementTree + + +################################################################################ +# export management + +class GLConstHeader: + def __init__(self, f): + self.f = f + + + def write(self, arg): + if isinstance(arg, list): + self.f.write('\n'.join(arg) + '\n') + elif isinstance(arg, (int, long)): + self.f.write('\n' * arg) + else: + self.f.write(str(arg) + '\n') + + + def formatFileBegin(self): + self.write([ + '/* 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 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 \'GLParseRegistryXML.py\'.', + ' */', + '' + ]) + + + def formatLibBegin(self, lib): + # lib would be 'GL', 'EGL', 'GLX' or 'WGL' + self.write('// ' + lib) + + + def formatLibConstant(self, 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 + + self.write(define + ' ' * whitespace + ' ' + value) + + + def formatLibEnd(self, lib): + # lib would be 'GL', 'EGL', 'GLX' or 'WGL' + self.write(2) + + + def formatFileEnd(self): + self.write([ + '', + '#endif // GLCONSTS_H_' + ]) + + +################################################################################ +# underground code + +def getScriptDir(): + return os.path.dirname(__file__) + '/' + + +def getXMLDir(): + if len(sys.argv) == 1: + return './' + + dirPath = sys.argv[1] + if dirPath[-1] != '/': + dirPath += '/' + + return dirPath + + +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 loadXML(self, path): + xmlPath = getXMLDir() + path + + if not os.path.isfile(xmlPath): + print 'missing file "' + xmlPath + '"' + return False + + tree = xml.etree.ElementTree.parse(xmlPath) + 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) + + return True + + + def exportConsts(self, path): + with open(getScriptDir() + path,'w') as f: + + headerFile = GLConstHeader(f) + headerFile.formatFileBegin() + + constNames = self.consts.keys() + constNames.sort() + + for lib in GLDatabase.LIBS: + headerFile.formatLibBegin(lib) + + for constName in constNames: + const = self.consts[constName] + + if const.lib != lib: + continue + + headerFile.formatLibConstant(lib, const.name, const.value) + + headerFile.formatLibEnd(lib) + + headerFile.formatFileEnd() + + +glDatabase = GLDatabase() + +success = glDatabase.loadXML('gl.xml') +success = success and glDatabase.loadXML('egl.xml') +success = success and glDatabase.loadXML('glx.xml') +success = success and glDatabase.loadXML('wgl.xml') + +if success: + glDatabase.exportConsts('GLConsts.h') diff --git a/gfx/gl/GLReadTexImageHelper.cpp b/gfx/gl/GLReadTexImageHelper.cpp new file mode 100644 index 0000000000..6593782282 --- /dev/null +++ b/gfx/gl/GLReadTexImageHelper.cpp @@ -0,0 +1,659 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "gfx2DGlue.h" +#include "gfxColor.h" +#include "gfxTypes.h" +#include "GLContext.h" +#include "OGLShaderProgram.h" +#include "ScopedGLHelpers.h" + +#include "mozilla/gfx/2D.h" +#include "mozilla/Move.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 (0x%04x) %s\n", + mGL->GLErrorToString(error), error, 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) { + 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 +ReadPixelsIntoDataSurface(GLContext* gl, DataSourceSurface* dest) +{ + gl->MakeCurrent(); + MOZ_ASSERT(dest->GetSize().width != 0); + MOZ_ASSERT(dest->GetSize().height != 0); + + bool hasAlpha = dest->GetFormat() == SurfaceFormat::B8G8R8A8 || + dest->GetFormat() == SurfaceFormat::R8G8B8A8; + + int destPixelSize; + GLenum destFormat; + GLenum destType; + + switch (dest->GetFormat()) { + 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(dest->GetFormat()); + MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride()); + + GLenum readFormat = destFormat; + GLenum readType = destType; + bool needsTempSurf = !GetActualReadFormats(gl, + destFormat, destType, + &readFormat, &readType); + + RefPtr<DataSourceSurface> tempSurf; + DataSourceSurface* readSurf = dest; + int readAlignment = GuessAlignment(dest->GetSize().width, + destPixelSize, + dest->Stride()); + if (!readAlignment) { + needsTempSurf = true; + } + if (needsTempSurf) { + if (GLContext::ShouldSpew()) { + NS_WARNING("Needing intermediary surface for ReadPixels. This will be slow!"); + } + SurfaceFormat readFormatGFX; + + 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 = dest->GetSize().width * BytesPerPixel(readFormatGFX); + tempSurf = Factory::CreateDataSourceSurfaceWithStride(dest->GetSize(), + readFormatGFX, + stride); + if (NS_WARN_IF(!tempSurf)) { + return; + } + + readSurf = tempSurf; + } + MOZ_ASSERT(readAlignment); + MOZ_ASSERT(reinterpret_cast<uintptr_t>(readSurf->GetData()) % readAlignment == 0); + + GLsizei width = dest->GetSize().width; + GLsizei height = dest->GetSize().height; + + { + ScopedPackState safePackState(gl); + gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, readAlignment); + + gl->fReadPixels(0, 0, + width, height, + readFormat, readType, + readSurf->GetData()); + } + + if (readSurf != dest) { + MOZ_ASSERT(readFormat == LOCAL_GL_RGBA); + MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); + gfx::Factory::CopyDataSourceSurface(readSurf, dest); + } +} + +already_AddRefed<gfx::DataSourceSurface> +YInvertImageSurface(gfx::DataSourceSurface* aSurf) +{ + RefPtr<DataSourceSurface> temp = + Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(), + aSurf->GetFormat(), + aSurf->Stride()); + 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->GuaranteeResolve(); + 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*)¤tPackAlignment); + if (currentPackAlignment != 4) { + gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4); + } + + gl->fGetTexImage(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, surf->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); + } + + 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"); + } + + /* Draw quad */ + mGL->fClearColor(1.0f, 0.0f, 1.0f, 1.0f); + mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT); + CLEANUP_IF_GLERROR_OCCURRED("when clearing color buffer"); + + 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..20d229e532 --- /dev/null +++ b/gfx/gl/GLReadTexImageHelper.h @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 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); + +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 100755 index 0000000000..463f7ebab3 --- /dev/null +++ b/gfx/gl/GLScreenBuffer.cpp @@ -0,0 +1,1044 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 <cstring> +#include "CompositorTypes.h" +#include "GLContext.h" +#include "GLBlitHelper.h" +#include "GLReadTexImageHelper.h" +#include "SharedSurfaceEGL.h" +#include "SharedSurfaceGL.h" +#include "ScopedGLHelpers.h" +#include "gfx2DGlue.h" +#include "../layers/ipc/ShadowLayers.h" +#include "mozilla/layers/TextureForwarder.h" +#include "mozilla/layers/TextureClientSharedSurface.h" + +#ifdef XP_WIN +#include "SharedSurfaceANGLE.h" // for SurfaceFactory_ANGLEShareHandle +#include "SharedSurfaceD3D11Interop.h" // for SurfaceFactory_D3D11Interop +#include "mozilla/gfx/DeviceManagerDx.h" +#endif + +#ifdef XP_MACOSX +#include "SharedSurfaceIO.h" +#endif + +#ifdef GL_PROVIDER_GLX +#include "GLXLibrary.h" +#include "SharedSurfaceGLX.h" +#endif + +namespace mozilla { +namespace gl { + +using gfx::SurfaceFormat; + +UniquePtr<GLScreenBuffer> +GLScreenBuffer::Create(GLContext* gl, + const gfx::IntSize& size, + const SurfaceCaps& caps) +{ + UniquePtr<GLScreenBuffer> ret; + if (caps.antialias && + !gl->IsSupported(GLFeature::framebuffer_multisample)) + { + return Move(ret); + } + + layers::TextureFlags flags = layers::TextureFlags::ORIGIN_BOTTOM_LEFT; + if (!caps.premultAlpha) { + flags |= layers::TextureFlags::NON_PREMULTIPLIED; + } + + UniquePtr<SurfaceFactory> factory = MakeUnique<SurfaceFactory_Basic>(gl, caps, flags); + + ret.reset( new GLScreenBuffer(gl, caps, Move(factory)) ); + return Move(ret); +} + +/* static */ UniquePtr<SurfaceFactory> +GLScreenBuffer::CreateFactory(GLContext* gl, + const SurfaceCaps& caps, + KnowsCompositor* compositorConnection, + const layers::TextureFlags& flags) +{ + return CreateFactory(gl, caps, compositorConnection->GetTextureForwarder(), + compositorConnection->GetCompositorBackendType(), flags); +} + +/* static */ UniquePtr<SurfaceFactory> +GLScreenBuffer::CreateFactory(GLContext* gl, + const SurfaceCaps& caps, + LayersIPCChannel* ipcChannel, + const mozilla::layers::LayersBackend backend, + const layers::TextureFlags& flags) +{ + UniquePtr<SurfaceFactory> factory = nullptr; + if (!gfxPrefs::WebGLForceLayersReadback()) { + switch (backend) { + case mozilla::layers::LayersBackend::LAYERS_OPENGL: { +#if defined(XP_MACOSX) + factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags); +#elif defined(GL_PROVIDER_GLX) + if (sGLXLibrary.UseTextureFromPixmap()) + factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags); +#elif defined(MOZ_WIDGET_UIKIT) + factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags); +#else + if (gl->GetContextType() == GLContextType::EGL) { + if (XRE_IsParentProcess()) { + factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags); + } + } +#endif + break; + } + case mozilla::layers::LayersBackend::LAYERS_D3D11: { +#ifdef XP_WIN + // Enable surface sharing only if ANGLE and compositing devices + // are both WARP or both not WARP + gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get(); + if (gl->IsANGLE() && + (gl->IsWARP() == dm->IsWARP()) && + dm->TextureSharingWorks()) + { + factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, ipcChannel, flags); + } + + if (!factory && gfxPrefs::WebGLDXGLEnabled()) { + factory = SurfaceFactory_D3D11Interop::Create(gl, caps, ipcChannel, flags); + } +#endif + break; + } + default: + break; + } + +#ifdef GL_PROVIDER_GLX + if (!factory && sGLXLibrary.UseTextureFromPixmap()) { + factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags); + } +#endif + } + + return factory; +} + +GLScreenBuffer::GLScreenBuffer(GLContext* gl, + const SurfaceCaps& caps, + UniquePtr<SurfaceFactory> factory) + : mGL(gl) + , mCaps(caps) + , mFactory(Move(factory)) + , mNeedsBlit(true) + , mUserReadBufferMode(LOCAL_GL_BACK) + , mUserDrawBufferMode(LOCAL_GL_BACK) + , mUserDrawFB(0) + , mUserReadFB(0) + , mInternalDrawFB(0) + , mInternalReadFB(0) +#ifdef DEBUG + , mInInternalMode_DrawFB(true) + , mInInternalMode_ReadFB(true) +#endif +{ } + +GLScreenBuffer::~GLScreenBuffer() +{ + mFactory = nullptr; + mDraw = nullptr; + mRead = nullptr; + + if (!mBack) + return; + + // Detach mBack cleanly. + mBack->Surf()->ProducerRelease(); +} + +void +GLScreenBuffer::BindAsFramebuffer(GLContext* const gl, GLenum target) const +{ + GLuint drawFB = DrawFB(); + GLuint readFB = ReadFB(); + + if (!gl->IsSupported(GLFeature::split_framebuffer)) { + MOZ_ASSERT(drawFB == readFB); + gl->raw_fBindFramebuffer(target, readFB); + return; + } + + switch (target) { + case LOCAL_GL_FRAMEBUFFER: + gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); + gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); + break; + + case LOCAL_GL_DRAW_FRAMEBUFFER_EXT: + gl->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, drawFB); + break; + + case LOCAL_GL_READ_FRAMEBUFFER_EXT: + gl->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, readFB); + break; + + default: + MOZ_CRASH("GFX: Bad `target` for BindFramebuffer."); + } +} + +void +GLScreenBuffer::BindFB(GLuint fb) +{ + GLuint drawFB = DrawFB(); + GLuint readFB = ReadFB(); + + mUserDrawFB = fb; + mUserReadFB = fb; + mInternalDrawFB = (fb == 0) ? drawFB : fb; + mInternalReadFB = (fb == 0) ? readFB : fb; + + if (mInternalDrawFB == mInternalReadFB) { + mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB); + } else { + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); + } + +#ifdef DEBUG + mInInternalMode_DrawFB = false; + mInInternalMode_ReadFB = false; +#endif +} + +void +GLScreenBuffer::BindDrawFB(GLuint fb) +{ + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + + GLuint drawFB = DrawFB(); + mUserDrawFB = fb; + mInternalDrawFB = (fb == 0) ? drawFB : fb; + + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); + +#ifdef DEBUG + mInInternalMode_DrawFB = false; +#endif +} + +void +GLScreenBuffer::BindReadFB(GLuint fb) +{ + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + + GLuint readFB = ReadFB(); + mUserReadFB = fb; + mInternalReadFB = (fb == 0) ? readFB : fb; + + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); + +#ifdef DEBUG + mInInternalMode_ReadFB = false; +#endif +} + +void +GLScreenBuffer::BindFB_Internal(GLuint fb) +{ + mInternalDrawFB = mUserDrawFB = fb; + mInternalReadFB = mUserReadFB = fb; + mGL->raw_fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mInternalDrawFB); + +#ifdef DEBUG + mInInternalMode_DrawFB = true; + mInInternalMode_ReadFB = true; +#endif +} + +void +GLScreenBuffer::BindDrawFB_Internal(GLuint fb) +{ + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + + mInternalDrawFB = mUserDrawFB = fb; + mGL->raw_fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, mInternalDrawFB); + +#ifdef DEBUG + mInInternalMode_DrawFB = true; +#endif +} + +void +GLScreenBuffer::BindReadFB_Internal(GLuint fb) +{ + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + + mInternalReadFB = mUserReadFB = fb; + mGL->raw_fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, mInternalReadFB); + +#ifdef DEBUG + mInInternalMode_ReadFB = true; +#endif +} + + +GLuint +GLScreenBuffer::GetDrawFB() const +{ +#ifdef DEBUG + MOZ_ASSERT(mGL->IsCurrent()); + MOZ_ASSERT(!mInInternalMode_DrawFB); + + // Don't need a branch here, because: + // LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT == LOCAL_GL_FRAMEBUFFER_BINDING == 0x8CA6 + // We use raw_ here because this is debug code and we need to see what + // the driver thinks. + GLuint actual = 0; + mGL->raw_fGetIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); + + GLuint predicted = mInternalDrawFB; + if (predicted != actual) { + printf_stderr("Misprediction: Bound draw FB predicted: %d. Was: %d.\n", + predicted, actual); + MOZ_ASSERT(false, "Draw FB binding misprediction!"); + } +#endif + + return mUserDrawFB; +} + +GLuint +GLScreenBuffer::GetReadFB() const +{ +#ifdef DEBUG + MOZ_ASSERT(mGL->IsCurrent()); + MOZ_ASSERT(!mInInternalMode_ReadFB); + + // We use raw_ here because this is debug code and we need to see what + // the driver thinks. + GLuint actual = 0; + if (mGL->IsSupported(GLFeature::split_framebuffer)) + mGL->raw_fGetIntegerv(LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT, (GLint*)&actual); + else + mGL->raw_fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)&actual); + + GLuint predicted = mInternalReadFB; + if (predicted != actual) { + printf_stderr("Misprediction: Bound read FB predicted: %d. Was: %d.\n", + predicted, actual); + MOZ_ASSERT(false, "Read FB binding misprediction!"); + } +#endif + + return mUserReadFB; +} + +GLuint +GLScreenBuffer::GetFB() const +{ + MOZ_ASSERT(GetDrawFB() == GetReadFB()); + return GetDrawFB(); +} + + +void +GLScreenBuffer::DeletingFB(GLuint fb) +{ + if (fb == mInternalDrawFB) { + mInternalDrawFB = 0; + mUserDrawFB = 0; + } + if (fb == mInternalReadFB) { + mInternalReadFB = 0; + mUserReadFB = 0; + } +} + + +void +GLScreenBuffer::AfterDrawCall() +{ + if (mUserDrawFB != 0) + return; + + RequireBlit(); +} + +void +GLScreenBuffer::BeforeReadCall() +{ + if (mUserReadFB != 0) + return; + + AssureBlitted(); +} + +bool +GLScreenBuffer::CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, + GLint y, GLsizei width, GLsizei height, GLint border) +{ + SharedSurface* surf; + if (GetReadFB() == 0) { + surf = SharedSurf(); + } else { + surf = mGL->mFBOMapping[GetReadFB()]; + } + if (surf) { + return surf->CopyTexImage2D(target, level, internalformat, x, y, width, height, border); + } + + return false; +} + +bool +GLScreenBuffer::ReadPixels(GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid* pixels) +{ + // If the currently bound framebuffer is backed by a SharedSurface + // then it might want to override how we read pixel data from it. + // This is normally only the default framebuffer, but we can also + // have SharedSurfaces bound to other framebuffers when doing + // readback for BasicLayers. + SharedSurface* surf; + if (GetReadFB() == 0) { + surf = SharedSurf(); + } else { + surf = mGL->mFBOMapping[GetReadFB()]; + } + if (surf) { + return surf->ReadPixels(x, y, width, height, format, type, pixels); + } + + return false; +} + +void +GLScreenBuffer::RequireBlit() +{ + mNeedsBlit = true; +} + +void +GLScreenBuffer::AssureBlitted() +{ + if (!mNeedsBlit) + return; + + if (mDraw) { + GLuint drawFB = DrawFB(); + GLuint readFB = ReadFB(); + + MOZ_ASSERT(drawFB != 0); + MOZ_ASSERT(drawFB != readFB); + MOZ_ASSERT(mGL->IsSupported(GLFeature::split_framebuffer)); + MOZ_ASSERT(mDraw->mSize == mRead->Size()); + + ScopedBindFramebuffer boundFB(mGL); + ScopedGLState scissor(mGL, LOCAL_GL_SCISSOR_TEST, false); + + BindReadFB_Internal(drawFB); + BindDrawFB_Internal(readFB); + + if (mGL->IsSupported(GLFeature::framebuffer_blit)) { + const gfx::IntSize& srcSize = mDraw->mSize; + const gfx::IntSize& destSize = mRead->Size(); + + mGL->raw_fBlitFramebuffer(0, 0, srcSize.width, srcSize.height, + 0, 0, destSize.width, destSize.height, + LOCAL_GL_COLOR_BUFFER_BIT, + LOCAL_GL_NEAREST); + } else if (mGL->IsExtensionSupported(GLContext::APPLE_framebuffer_multisample)) { + mGL->fResolveMultisampleFramebufferAPPLE(); + } else { + MOZ_CRASH("GFX: No available blit methods."); + } + // Done! + } + + mNeedsBlit = false; +} + +void +GLScreenBuffer::Morph(UniquePtr<SurfaceFactory> newFactory) +{ + MOZ_RELEASE_ASSERT(newFactory, "newFactory must not be null"); + mFactory = Move(newFactory); +} + +bool +GLScreenBuffer::Attach(SharedSurface* surf, const gfx::IntSize& size) +{ + ScopedBindFramebuffer autoFB(mGL); + + const bool readNeedsUnlock = (mRead && SharedSurf()); + if (readNeedsUnlock) { + SharedSurf()->UnlockProd(); + } + + surf->LockProd(); + + if (mRead && + surf->mAttachType == SharedSurf()->mAttachType && + size == Size()) + { + // Same size, same type, ready for reuse! + mRead->Attach(surf); + } else { + // Else something changed, so resize: + UniquePtr<DrawBuffer> draw; + bool drawOk = true; + + /* Don't change out the draw buffer unless we resize. In the + * preserveDrawingBuffer:true case, prior contents of the buffer must + * be retained. If we're using a draw buffer, it's an MSAA buffer, so + * even if we copy the previous frame into the (single-sampled) read + * buffer, if we need to re-resolve from draw to read (as triggered by + * drawing), we'll need the old MSAA content to still be in the draw + * buffer. + */ + if (!mDraw || size != Size()) + drawOk = CreateDraw(size, &draw); // Can be null. + + UniquePtr<ReadBuffer> read = CreateRead(surf); + bool readOk = !!read; + + if (!drawOk || !readOk) { + surf->UnlockProd(); + if (readNeedsUnlock) { + SharedSurf()->LockProd(); + } + return false; + } + + if (draw) + mDraw = Move(draw); + + mRead = Move(read); + } + + // Check that we're all set up. + MOZ_ASSERT(SharedSurf() == surf); + + // Update the ReadBuffer mode. + if (mGL->IsSupported(gl::GLFeature::read_buffer)) { + BindFB(0); + mRead->SetReadBuffer(mUserReadBufferMode); + } + + // Update the DrawBuffer mode. + if (mGL->IsSupported(gl::GLFeature::draw_buffers)) { + BindFB(0); + SetDrawBuffer(mUserDrawBufferMode); + } + + RequireBlit(); + + return true; +} + +bool +GLScreenBuffer::Swap(const gfx::IntSize& size) +{ + RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size); + if (!newBack) + return false; + + // In the case of DXGL interop, the new surface needs to be acquired before + // it is attached so that the interop surface is locked, which populates + // the GL renderbuffer. This results in the renderbuffer being ready and + // attachment to framebuffer succeeds in Attach() call. + newBack->Surf()->ProducerAcquire(); + + if (!Attach(newBack->Surf(), size)) { + newBack->Surf()->ProducerRelease(); + return false; + } + // Attach was successful. + + mFront = mBack; + mBack = newBack; + + if (ShouldPreserveBuffer() && + mFront && + mBack && + !mDraw) + { + auto src = mFront->Surf(); + auto dest = mBack->Surf(); + + //uint32_t srcPixel = ReadPixel(src); + //uint32_t destPixel = ReadPixel(dest); + //printf_stderr("Before: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel); +#ifdef DEBUG + GLContext::LocalErrorScope errorScope(*mGL); +#endif + + SharedSurface::ProdCopy(src, dest, mFactory.get()); + +#ifdef DEBUG + MOZ_ASSERT(!errorScope.GetError()); +#endif + + //srcPixel = ReadPixel(src); + //destPixel = ReadPixel(dest); + //printf_stderr("After: src: 0x%08x, dest: 0x%08x\n", srcPixel, destPixel); + } + + // XXX: We would prefer to fence earlier on platforms that don't need + // the full ProducerAcquire/ProducerRelease semantics, so that the fence + // doesn't include the copy operation. Unfortunately, the current API + // doesn't expose a good way to do that. + if (mFront) { + mFront->Surf()->ProducerRelease(); + } + + return true; +} + +bool +GLScreenBuffer::PublishFrame(const gfx::IntSize& size) +{ + AssureBlitted(); + + bool good = Swap(size); + return good; +} + +bool +GLScreenBuffer::Resize(const gfx::IntSize& size) +{ + RefPtr<SharedSurfaceTextureClient> newBack = mFactory->NewTexClient(size); + if (!newBack) + return false; + + if (!Attach(newBack->Surf(), size)) + return false; + + if (mBack) + mBack->Surf()->ProducerRelease(); + + mBack = newBack; + + mBack->Surf()->ProducerAcquire(); + + return true; +} + +bool +GLScreenBuffer::CreateDraw(const gfx::IntSize& size, + UniquePtr<DrawBuffer>* out_buffer) +{ + GLContext* gl = mFactory->mGL; + const GLFormats& formats = mFactory->mFormats; + const SurfaceCaps& caps = mFactory->DrawCaps(); + + return DrawBuffer::Create(gl, caps, formats, size, out_buffer); +} + +UniquePtr<ReadBuffer> +GLScreenBuffer::CreateRead(SharedSurface* surf) +{ + GLContext* gl = mFactory->mGL; + const GLFormats& formats = mFactory->mFormats; + const SurfaceCaps& caps = mFactory->ReadCaps(); + + return ReadBuffer::Create(gl, caps, formats, surf); +} + +void +GLScreenBuffer::SetDrawBuffer(GLenum mode) +{ + MOZ_ASSERT(mGL->IsSupported(gl::GLFeature::draw_buffers)); + MOZ_ASSERT(GetDrawFB() == 0); + + if (!mGL->IsSupported(GLFeature::draw_buffers)) + return; + + mUserDrawBufferMode = mode; + + GLuint fb = mDraw ? mDraw->mFB : mRead->mFB; + GLenum internalMode; + + switch (mode) { + case LOCAL_GL_BACK: + internalMode = (fb == 0) ? LOCAL_GL_BACK + : LOCAL_GL_COLOR_ATTACHMENT0; + break; + + case LOCAL_GL_NONE: + internalMode = LOCAL_GL_NONE; + break; + + default: + MOZ_CRASH("GFX: Bad value."); + } + + mGL->MakeCurrent(); + mGL->fDrawBuffers(1, &internalMode); +} + +void +GLScreenBuffer::SetReadBuffer(GLenum mode) +{ + MOZ_ASSERT(mGL->IsSupported(gl::GLFeature::read_buffer)); + MOZ_ASSERT(GetReadFB() == 0); + + mUserReadBufferMode = mode; + mRead->SetReadBuffer(mUserReadBufferMode); +} + +bool +GLScreenBuffer::IsDrawFramebufferDefault() const +{ + if (!mDraw) + return IsReadFramebufferDefault(); + return mDraw->mFB == 0; +} + +bool +GLScreenBuffer::IsReadFramebufferDefault() const +{ + return SharedSurf()->mAttachType == AttachmentType::Screen; +} + +uint32_t +GLScreenBuffer::DepthBits() const +{ + const GLFormats& formats = mFactory->mFormats; + + if (formats.depth == LOCAL_GL_DEPTH_COMPONENT16) + return 16; + + return 24; +} + +//////////////////////////////////////////////////////////////////////// +// Utils + +static void +RenderbufferStorageBySamples(GLContext* aGL, GLsizei aSamples, + GLenum aInternalFormat, const gfx::IntSize& aSize) +{ + if (aSamples) { + aGL->fRenderbufferStorageMultisample(LOCAL_GL_RENDERBUFFER, + aSamples, + aInternalFormat, + aSize.width, aSize.height); + } else { + aGL->fRenderbufferStorage(LOCAL_GL_RENDERBUFFER, + aInternalFormat, + aSize.width, aSize.height); + } +} + +static GLuint +CreateRenderbuffer(GLContext* aGL, GLenum aFormat, GLsizei aSamples, + const gfx::IntSize& aSize) +{ + GLuint rb = 0; + aGL->fGenRenderbuffers(1, &rb); + ScopedBindRenderbuffer autoRB(aGL, rb); + + RenderbufferStorageBySamples(aGL, aSamples, aFormat, aSize); + + return rb; +} + +static void +CreateRenderbuffersForOffscreen(GLContext* aGL, const GLFormats& aFormats, + const gfx::IntSize& aSize, bool aMultisample, + GLuint* aColorMSRB, GLuint* aDepthRB, + GLuint* aStencilRB) +{ + GLsizei samples = aMultisample ? aFormats.samples : 0; + if (aColorMSRB) { + MOZ_ASSERT(aFormats.samples > 0); + MOZ_ASSERT(aFormats.color_rbFormat); + + GLenum colorFormat = aFormats.color_rbFormat; + if (aGL->IsANGLE()) { + MOZ_ASSERT(colorFormat == LOCAL_GL_RGBA8); + colorFormat = LOCAL_GL_BGRA8_EXT; + } + + *aColorMSRB = CreateRenderbuffer(aGL, colorFormat, samples, aSize); + } + + if (aDepthRB && + aStencilRB && + aFormats.depthStencil) + { + *aDepthRB = CreateRenderbuffer(aGL, aFormats.depthStencil, samples, aSize); + *aStencilRB = *aDepthRB; + } else { + if (aDepthRB) { + MOZ_ASSERT(aFormats.depth); + + *aDepthRB = CreateRenderbuffer(aGL, aFormats.depth, samples, aSize); + } + + if (aStencilRB) { + MOZ_ASSERT(aFormats.stencil); + + *aStencilRB = CreateRenderbuffer(aGL, aFormats.stencil, samples, aSize); + } + } +} + +//////////////////////////////////////////////////////////////////////// +// DrawBuffer + +bool +DrawBuffer::Create(GLContext* const gl, + const SurfaceCaps& caps, + const GLFormats& formats, + const gfx::IntSize& size, + UniquePtr<DrawBuffer>* out_buffer) +{ + MOZ_ASSERT(out_buffer); + *out_buffer = nullptr; + + if (!caps.color) { + MOZ_ASSERT(!caps.alpha && !caps.depth && !caps.stencil); + + // Nothing is needed. + return true; + } + + if (caps.antialias) { + if (formats.samples == 0) + return false; // Can't create it. + + MOZ_ASSERT(formats.samples <= gl->MaxSamples()); + } + + GLuint colorMSRB = 0; + GLuint depthRB = 0; + GLuint stencilRB = 0; + + GLuint* pColorMSRB = caps.antialias ? &colorMSRB : nullptr; + GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; + GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; + + if (!formats.color_rbFormat) + pColorMSRB = nullptr; + + if (pDepthRB && pStencilRB) { + if (!formats.depth && !formats.depthStencil) + pDepthRB = nullptr; + + if (!formats.stencil && !formats.depthStencil) + pStencilRB = nullptr; + } else { + if (!formats.depth) + pDepthRB = nullptr; + + if (!formats.stencil) + pStencilRB = nullptr; + } + + GLContext::LocalErrorScope localError(*gl); + + CreateRenderbuffersForOffscreen(gl, formats, size, caps.antialias, + pColorMSRB, pDepthRB, pStencilRB); + + GLuint fb = 0; + gl->fGenFramebuffers(1, &fb); + gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb); + + const GLsizei samples = formats.samples; + UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, samples, fb, colorMSRB, + depthRB, stencilRB) ); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY); + if (err || !gl->IsFramebufferComplete(fb)) + return false; + + *out_buffer = Move(ret); + return true; +} + +DrawBuffer::~DrawBuffer() +{ + if (!mGL->MakeCurrent()) + return; + + GLuint fb = mFB; + GLuint rbs[] = { + mColorMSRB, + mDepthRB, + mStencilRB + }; + + mGL->fDeleteFramebuffers(1, &fb); + mGL->fDeleteRenderbuffers(3, rbs); +} + +//////////////////////////////////////////////////////////////////////// +// ReadBuffer + +UniquePtr<ReadBuffer> +ReadBuffer::Create(GLContext* gl, + const SurfaceCaps& caps, + const GLFormats& formats, + SharedSurface* surf) +{ + MOZ_ASSERT(surf); + + if (surf->mAttachType == AttachmentType::Screen) { + // Don't need anything. Our read buffer will be the 'screen'. + return UniquePtr<ReadBuffer>( new ReadBuffer(gl, 0, 0, 0, + surf) ); + } + + GLuint depthRB = 0; + GLuint stencilRB = 0; + + GLuint* pDepthRB = caps.depth ? &depthRB : nullptr; + GLuint* pStencilRB = caps.stencil ? &stencilRB : nullptr; + + GLContext::LocalErrorScope localError(*gl); + + CreateRenderbuffersForOffscreen(gl, formats, surf->mSize, caps.antialias, + nullptr, pDepthRB, pStencilRB); + + GLuint colorTex = 0; + GLuint colorRB = 0; + GLenum target = 0; + + switch (surf->mAttachType) { + case AttachmentType::GLTexture: + colorTex = surf->ProdTexture(); + target = surf->ProdTextureTarget(); + break; + case AttachmentType::GLRenderbuffer: + colorRB = surf->ProdRenderbuffer(); + break; + default: + MOZ_CRASH("GFX: Unknown attachment type, create?"); + } + MOZ_ASSERT(colorTex || colorRB); + + GLuint fb = 0; + gl->fGenFramebuffers(1, &fb); + gl->AttachBuffersToFB(colorTex, colorRB, depthRB, stencilRB, fb, target); + gl->mFBOMapping[fb] = surf; + + UniquePtr<ReadBuffer> ret( new ReadBuffer(gl, fb, depthRB, + stencilRB, surf) ); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) + return nullptr; + + const bool needsAcquire = !surf->IsProducerAcquired(); + if (needsAcquire) { + surf->ProducerReadAcquire(); + } + const bool isComplete = gl->IsFramebufferComplete(fb); + if (needsAcquire) { + surf->ProducerReadRelease(); + } + + if (!isComplete) + return nullptr; + + return Move(ret); +} + +ReadBuffer::~ReadBuffer() +{ + if (!mGL->MakeCurrent()) + return; + + GLuint fb = mFB; + GLuint rbs[] = { + mDepthRB, + mStencilRB + }; + + mGL->fDeleteFramebuffers(1, &fb); + mGL->fDeleteRenderbuffers(2, rbs); + mGL->mFBOMapping.erase(mFB); +} + +void +ReadBuffer::Attach(SharedSurface* surf) +{ + MOZ_ASSERT(surf && mSurf); + MOZ_ASSERT(surf->mAttachType == mSurf->mAttachType); + MOZ_ASSERT(surf->mSize == mSurf->mSize); + + // Nothing else is needed for AttachType Screen. + if (surf->mAttachType != AttachmentType::Screen) { + GLuint colorTex = 0; + GLuint colorRB = 0; + GLenum target = 0; + + switch (surf->mAttachType) { + case AttachmentType::GLTexture: + colorTex = surf->ProdTexture(); + target = surf->ProdTextureTarget(); + break; + case AttachmentType::GLRenderbuffer: + colorRB = surf->ProdRenderbuffer(); + break; + default: + MOZ_CRASH("GFX: Unknown attachment type, attach?"); + } + + mGL->AttachBuffersToFB(colorTex, colorRB, 0, 0, mFB, target); + mGL->mFBOMapping[mFB] = surf; + MOZ_ASSERT(mGL->IsFramebufferComplete(mFB)); + } + + mSurf = surf; +} + +const gfx::IntSize& +ReadBuffer::Size() const +{ + return mSurf->mSize; +} + +void +ReadBuffer::SetReadBuffer(GLenum userMode) const +{ + if (!mGL->IsSupported(GLFeature::read_buffer)) + return; + + GLenum internalMode; + + switch (userMode) { + case LOCAL_GL_BACK: + case LOCAL_GL_FRONT: + internalMode = (mFB == 0) ? userMode + : LOCAL_GL_COLOR_ATTACHMENT0; + break; + + case LOCAL_GL_NONE: + internalMode = LOCAL_GL_NONE; + break; + + default: + MOZ_CRASH("GFX: Bad value."); + } + + mGL->MakeCurrent(); + mGL->fReadBuffer(internalMode); +} + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/GLScreenBuffer.h b/gfx/gl/GLScreenBuffer.h new file mode 100644 index 0000000000..6cacf221db --- /dev/null +++ b/gfx/gl/GLScreenBuffer.h @@ -0,0 +1,301 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "GLContextTypes.h" +#include "GLDefs.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/UniquePtr.h" +#include "SharedSurface.h" +#include "SurfaceTypes.h" + +namespace mozilla { +namespace layers { +class KnowsCompositor; +class LayersIPCChannel; +class SharedSurfaceTextureClient; +} // namespace layers + +namespace gl { + +class GLContext; +class SharedSurface; +class ShSurfHandle; +class SurfaceFactory; + +class DrawBuffer +{ +public: + // Fallible! + // But it may return true with *out_buffer==nullptr if unneeded. + static bool Create(GLContext* const gl, + const SurfaceCaps& caps, + const GLFormats& formats, + const gfx::IntSize& size, + UniquePtr<DrawBuffer>* out_buffer); + +protected: + GLContext* const mGL; +public: + const gfx::IntSize mSize; + const GLsizei mSamples; + const GLuint mFB; +protected: + const GLuint mColorMSRB; + const GLuint mDepthRB; + const GLuint mStencilRB; + + DrawBuffer(GLContext* gl, + const gfx::IntSize& size, + GLsizei samples, + GLuint fb, + GLuint colorMSRB, + GLuint depthRB, + GLuint stencilRB) + : mGL(gl) + , mSize(size) + , mSamples(samples) + , mFB(fb) + , mColorMSRB(colorMSRB) + , mDepthRB(depthRB) + , mStencilRB(stencilRB) + {} + +public: + virtual ~DrawBuffer(); +}; + +class ReadBuffer +{ +public: + // Infallible, always non-null. + static UniquePtr<ReadBuffer> Create(GLContext* gl, + const SurfaceCaps& caps, + const GLFormats& formats, + SharedSurface* surf); + +protected: + GLContext* const mGL; +public: + const GLuint mFB; +protected: + // mFB has the following attachments: + const GLuint mDepthRB; + const GLuint mStencilRB; + // note no mColorRB here: this is provided by mSurf. + SharedSurface* mSurf; + + ReadBuffer(GLContext* gl, + GLuint fb, + GLuint depthRB, + GLuint stencilRB, + SharedSurface* surf) + : mGL(gl) + , mFB(fb) + , mDepthRB(depthRB) + , mStencilRB(stencilRB) + , mSurf(surf) + {} + +public: + virtual ~ReadBuffer(); + + // Cannot attach a surf of a different AttachType or Size than before. + void Attach(SharedSurface* surf); + + const gfx::IntSize& Size() const; + + SharedSurface* SharedSurf() const { + return mSurf; + } + + void SetReadBuffer(GLenum mode) const; +}; + + +class GLScreenBuffer +{ +public: + // Infallible. + static UniquePtr<GLScreenBuffer> Create(GLContext* gl, + const gfx::IntSize& size, + const SurfaceCaps& caps); + + static UniquePtr<SurfaceFactory> + CreateFactory(GLContext* gl, + const SurfaceCaps& caps, + layers::KnowsCompositor* compositorConnection, + const layers::TextureFlags& flags); + static UniquePtr<SurfaceFactory> + CreateFactory(GLContext* gl, + const SurfaceCaps& caps, + layers::LayersIPCChannel* ipcChannel, + const mozilla::layers::LayersBackend backend, + const layers::TextureFlags& flags); + +protected: + GLContext* const mGL; // Owns us. +public: + const SurfaceCaps mCaps; +protected: + UniquePtr<SurfaceFactory> mFactory; + + RefPtr<layers::SharedSurfaceTextureClient> mBack; + RefPtr<layers::SharedSurfaceTextureClient> mFront; + + UniquePtr<DrawBuffer> mDraw; + UniquePtr<ReadBuffer> mRead; + + bool mNeedsBlit; + + GLenum mUserReadBufferMode; + GLenum mUserDrawBufferMode; + + // Below are the parts that help us pretend to be framebuffer 0: + GLuint mUserDrawFB; + GLuint mUserReadFB; + GLuint mInternalDrawFB; + GLuint mInternalReadFB; + +#ifdef DEBUG + bool mInInternalMode_DrawFB; + bool mInInternalMode_ReadFB; +#endif + + GLScreenBuffer(GLContext* gl, + const SurfaceCaps& caps, + UniquePtr<SurfaceFactory> factory); + +public: + virtual ~GLScreenBuffer(); + + SurfaceFactory* Factory() const { + return mFactory.get(); + } + + const RefPtr<layers::SharedSurfaceTextureClient>& Front() const { + return mFront; + } + + SharedSurface* SharedSurf() const { + MOZ_ASSERT(mRead); + return mRead->SharedSurf(); + } + + bool ShouldPreserveBuffer() const { + return mCaps.preserve; + } + + GLuint DrawFB() const { + if (!mDraw) + return ReadFB(); + + return mDraw->mFB; + } + + GLuint ReadFB() const { + return mRead->mFB; + } + + GLsizei Samples() const { + if (!mDraw) + return 0; + + return mDraw->mSamples; + } + + uint32_t DepthBits() const; + + void DeletingFB(GLuint fb); + + const gfx::IntSize& Size() const { + MOZ_ASSERT(mRead); + MOZ_ASSERT(!mDraw || mDraw->mSize == mRead->Size()); + return mRead->Size(); + } + + void BindAsFramebuffer(GLContext* const gl, GLenum target) const; + + void RequireBlit(); + void AssureBlitted(); + void AfterDrawCall(); + void BeforeReadCall(); + + bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, + GLint y, GLsizei width, GLsizei height, GLint border); + + void SetReadBuffer(GLenum userMode); + void SetDrawBuffer(GLenum userMode); + + GLenum GetReadBufferMode() const { return mUserReadBufferMode; } + GLenum GetDrawBufferMode() const { return mUserDrawBufferMode; } + + /** + * Attempts to read pixels from the current bound framebuffer, if + * it is backed by a SharedSurface. + * + * Returns true if the pixel data has been read back, false + * otherwise. + */ + bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid* pixels); + + // Morph changes the factory used to create surfaces. + void Morph(UniquePtr<SurfaceFactory> newFactory); + +protected: + // Returns false on error or inability to resize. + bool Swap(const gfx::IntSize& size); + +public: + bool PublishFrame(const gfx::IntSize& size); + + bool Resize(const gfx::IntSize& size); + +protected: + bool Attach(SharedSurface* surf, const gfx::IntSize& size); + + bool CreateDraw(const gfx::IntSize& size, UniquePtr<DrawBuffer>* out_buffer); + UniquePtr<ReadBuffer> CreateRead(SharedSurface* surf); + +public: + /* `fb` in these functions is the framebuffer the GLContext is hoping to + * bind. When this is 0, we intercept the call and bind our own + * framebuffers. As a client of these functions, just bind 0 when you want + * to draw to the default framebuffer/'screen'. + */ + void BindFB(GLuint fb); + void BindDrawFB(GLuint fb); + void BindReadFB(GLuint fb); + GLuint GetFB() const; + GLuint GetDrawFB() const; + GLuint GetReadFB() const; + + // Here `fb` is the actual framebuffer you want bound. Binding 0 will + // bind the (generally useless) default framebuffer. + void BindFB_Internal(GLuint fb); + void BindDrawFB_Internal(GLuint fb); + void BindReadFB_Internal(GLuint fb); + + bool IsDrawFramebufferDefault() const; + bool IsReadFramebufferDefault() const; +}; + +} // 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..c91d558af4 --- /dev/null +++ b/gfx/gl/GLTextureImage.cpp @@ -0,0 +1,521 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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" + +#include "TextureImageEGL.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) +{ + switch (gl->GetContextType()) { + case GLContextType::EGL: + return CreateTextureImageEGL(gl, aSize, aContentType, aWrapMode, aFlags, aImageFormat); + default: { + 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) +{ + switch (gl->GetContextType()) { + case GLContextType::EGL: + return TileGenFuncEGL(gl, aSize, aContentType, aFlags, aImageFormat); + default: + 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* aSrcPoint) +{ + nsIntRegion destRegion = aDestRegion ? *aDestRegion + : IntRect(0, 0, + aSurface->GetSize().width, + aSurface->GetSize().height); + gfx::IntPoint srcPoint = aSrcPoint ? *aSrcPoint + : gfx::IntPoint(0, 0); + return DirectUpdate(aSurface, destRegion, srcPoint); +} + +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->IsOwningThreadCurrent()) { + 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& aFrom /* = 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, + aFrom); + + 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 (!CanUploadSubTextures(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) + , 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() +{ +} + +bool +TiledTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0, 0) */) +{ + 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, aFrom + 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. + unsigned int length = mImages.Length(); + for (; i < length; i++) + mImages.RemoveElementAt(mImages.Length()-1); + + // 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..1dd22fb543 --- /dev/null +++ b/gfx/gl/GLTextureImage.h @@ -0,0 +1,306 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 + * aFrom - offset in the source to update from + */ + virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)) = 0; + bool UpdateFromDataSource(gfx::DataSourceSurface* aSurf, + const nsIntRegion* aDstRegion = nullptr, + const gfx::IntPoint* aSrcOffset = 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); + + virtual void BindTexture(GLenum aTextureUnit); + + virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)); + virtual GLuint GetTextureID() { return mTexture; } + + virtual void MarkValid() { mTextureState = Valid; } + + virtual void Resize(const gfx::IntSize& aSize); + +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); + ~TiledTextureImage(); + void DumpDiv(); + virtual void Resize(const gfx::IntSize& aSize); + virtual uint32_t GetTileCount(); + virtual void BeginBigImageIteration(); + virtual bool NextTile(); + virtual void SetIterationCallback(BigImageIterationCallback aCallback, + void* aCallbackData); + virtual gfx::IntRect GetTileRect(); + virtual GLuint GetTextureID() { + return mImages[mCurrentImage]->GetTextureID(); + } + virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)); + virtual void BindTexture(GLenum); + +protected: + virtual gfx::IntRect GetSrcTileRect(); + + 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..af27019862 --- /dev/null +++ b/gfx/gl/GLTypes.h @@ -0,0 +1,94 @@ +/* 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(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 int8_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_ +typedef intptr_t GLsizeiptr; +typedef intptr_t GLintptr; +#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 void* EGLConfig; +typedef void* EGLContext; +typedef void* EGLDisplay; +typedef void* EGLSurface; +typedef void* EGLClientBuffer; +typedef void* EGLCastToRelevantPtr; +typedef void* EGLImage; +typedef void* EGLSync; +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) + +#endif diff --git a/gfx/gl/GLUploadHelpers.cpp b/gfx/gl/GLUploadHelpers.cpp new file mode 100644 index 0000000000..75165eedf7 --- /dev/null +++ b/gfx/gl/GLUploadHelpers.cpp @@ -0,0 +1,558 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 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 +CanUploadSubTextures(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; + 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. + unsigned char* newPixels = new (fallible) unsigned char[width*height*pixelsize]; + + 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)) { + 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); + + GLvoid* paddedPixels = new unsigned char[paddedWidth * paddedHeight * pixelsize]; + + // 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, + 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: + internalFormat = format = LOCAL_GL_LUMINANCE; + type = LOCAL_GL_UNSIGNED_BYTE; + // We don't have a specific luminance shader + surfaceFormat = SurfaceFormat::A8; + break; + default: + NS_ASSERTION(false, "Unhandled image surface format!"); + } + + if (aOutUploadSize) { + *aOutUploadSize = 0; + } + + if (aNeedInit || !CanUploadSubTextures(gl)) { + // 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()) { + const IntRect& rect = iter.Get(); + const unsigned char* rectData = + aData + DataOffset(rect.TopLeft(), aStride, aFormat); + + 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& aSrcPoint, + GLenum aTextureUnit, + GLenum aTextureTarget) +{ + + int32_t stride = aSurface->Stride(); + SurfaceFormat format = aSurface->GetFormat(); + unsigned char* data = aSurface->GetData() + + DataOffset(aSrcPoint, stride, format); + + return UploadImageDataToTexture(gl, data, 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..866d44adbe --- /dev/null +++ b/gfx/gl/GLUploadHelpers.h @@ -0,0 +1,84 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 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, + 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& aSrcPoint = gfx::IntPoint(0, 0), + GLenum aTextureUnit = LOCAL_GL_TEXTURE0, + GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D); + +bool CanUploadSubTextures(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..d584b3b417 --- /dev/null +++ b/gfx/gl/GLXLibrary.h @@ -0,0 +1,274 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 GFX_GLXLIBRARY_H +#define GFX_GLXLIBRARY_H + +#include "GLContextTypes.h" +typedef realGLboolean GLboolean; + +// stuff from glx.h +#include "X11/Xlib.h" +typedef struct __GLXcontextRec* GLXContext; +typedef XID GLXPixmap; +typedef XID GLXDrawable; +/* GLX 1.3 and later */ +typedef struct __GLXFBConfigRec* GLXFBConfig; +typedef XID GLXFBConfigID; +typedef XID GLXContextID; +typedef XID GLXWindow; +typedef XID GLXPbuffer; +// end of stuff from glx.h +#include "prenv.h" + +struct PRLibrary; +class gfxASurface; + +namespace mozilla { +namespace gl { + +class GLXLibrary +{ +public: + constexpr GLXLibrary() + : xDestroyContextInternal(nullptr) + , xMakeCurrentInternal(nullptr) + , xGetCurrentContextInternal(nullptr) + , xGetProcAddressInternal(nullptr) + , xChooseFBConfigInternal(nullptr) + , xGetFBConfigsInternal(nullptr) + , xCreateNewContextInternal(nullptr) + , xGetFBConfigAttribInternal(nullptr) + , xSwapBuffersInternal(nullptr) + , xQueryExtensionsStringInternal(nullptr) + , xGetClientStringInternal(nullptr) + , xQueryServerStringInternal(nullptr) + , xCreatePixmapInternal(nullptr) + , xCreateGLXPixmapWithConfigInternal(nullptr) + , xDestroyPixmapInternal(nullptr) + , xQueryVersionInternal(nullptr) + , xBindTexImageInternal(nullptr) + , xReleaseTexImageInternal(nullptr) + , xWaitGLInternal(nullptr) + , xWaitXInternal(nullptr) + , xCreateContextAttribsInternal(nullptr) + , xGetVideoSyncInternal(nullptr) + , xWaitVideoSyncInternal(nullptr) + , xSwapIntervalInternal(nullptr) + , mInitialized(false), mTriedInitializing(false) + , mUseTextureFromPixmap(false), mDebug(false) + , mHasRobustness(false), mHasCreateContextAttribs(false) + , mHasVideoSync(false) + , mIsATI(false), mIsNVIDIA(false) + , mClientIsMesa(false), mGLXMajorVersion(0) + , mGLXMinorVersion(0) + , mOGLLibrary(nullptr) + {} + + void xDestroyContext(Display* display, GLXContext context); + Bool xMakeCurrent(Display* display, + GLXDrawable drawable, + GLXContext context); + + GLXContext xGetCurrentContext(); + static void* xGetProcAddress(const char* procName); + GLXFBConfig* xChooseFBConfig(Display* display, + int screen, + const int* attrib_list, + int* nelements); + GLXFBConfig* xGetFBConfigs(Display* display, + int screen, + int* nelements); + GLXContext xCreateNewContext(Display* display, + GLXFBConfig config, + int render_type, + GLXContext share_list, + Bool direct); + int xGetFBConfigAttrib(Display* display, + GLXFBConfig config, + int attribute, + int* value); + void xSwapBuffers(Display* display, GLXDrawable drawable); + const char* xQueryExtensionsString(Display* display, + int screen); + const char* xGetClientString(Display* display, + int screen); + const char* xQueryServerString(Display* display, + int screen, int name); + GLXPixmap xCreatePixmap(Display* display, + GLXFBConfig config, + Pixmap pixmap, + const int* attrib_list); + GLXPixmap xCreateGLXPixmapWithConfig(Display* display, + GLXFBConfig config, + Pixmap pixmap); + void xDestroyPixmap(Display* display, GLXPixmap pixmap); + Bool xQueryVersion(Display* display, + int* major, + int* minor); + void xBindTexImage(Display* display, + GLXDrawable drawable, + int buffer, + const int* attrib_list); + void xReleaseTexImage(Display* display, + GLXDrawable drawable, + int buffer); + void xWaitGL(); + void xWaitX(); + + GLXContext xCreateContextAttribs(Display* display, + GLXFBConfig config, + GLXContext share_list, + Bool direct, + const int* attrib_list); + + int xGetVideoSync(unsigned int* count); + int xWaitVideoSync(int divisor, int remainder, unsigned int* count); + void xSwapInterval(Display* dpy, GLXDrawable drawable, int interval); + + bool EnsureInitialized(); + + GLXPixmap CreatePixmap(gfxASurface* aSurface); + void DestroyPixmap(Display* aDisplay, GLXPixmap aPixmap); + void BindTexImage(Display* aDisplay, GLXPixmap aPixmap); + void ReleaseTexImage(Display* aDisplay, GLXPixmap aPixmap); + void UpdateTexImage(Display* aDisplay, GLXPixmap aPixmap); + + bool UseTextureFromPixmap() { return mUseTextureFromPixmap; } + bool HasRobustness() { return mHasRobustness; } + bool HasCreateContextAttribs() { return mHasCreateContextAttribs; } + bool SupportsTextureFromPixmap(gfxASurface* aSurface); + bool SupportsVideoSync(); + bool SupportsSwapControl() const { return bool(xSwapIntervalInternal); } + bool IsATI() { return mIsATI; } + bool IsMesa() { return mClientIsMesa; } + bool GLXVersionCheck(int aMajor, int aMinor); + +private: + + typedef void (GLAPIENTRY * PFNGLXDESTROYCONTEXTPROC) (Display*, + GLXContext); + PFNGLXDESTROYCONTEXTPROC xDestroyContextInternal; + typedef Bool (GLAPIENTRY * PFNGLXMAKECURRENTPROC) (Display*, + GLXDrawable, + GLXContext); + PFNGLXMAKECURRENTPROC xMakeCurrentInternal; + typedef GLXContext (GLAPIENTRY * PFNGLXGETCURRENTCONTEXT) (); + PFNGLXGETCURRENTCONTEXT xGetCurrentContextInternal; + typedef void* (GLAPIENTRY * PFNGLXGETPROCADDRESSPROC) (const char*); + PFNGLXGETPROCADDRESSPROC xGetProcAddressInternal; + typedef GLXFBConfig* (GLAPIENTRY * PFNGLXCHOOSEFBCONFIG) (Display*, + int, + const int*, + int*); + PFNGLXCHOOSEFBCONFIG xChooseFBConfigInternal; + typedef GLXFBConfig* (GLAPIENTRY * PFNGLXGETFBCONFIGS) (Display*, + int, + int*); + PFNGLXGETFBCONFIGS xGetFBConfigsInternal; + typedef GLXContext (GLAPIENTRY * PFNGLXCREATENEWCONTEXT) (Display*, + GLXFBConfig, + int, + GLXContext, + Bool); + PFNGLXCREATENEWCONTEXT xCreateNewContextInternal; + typedef int (GLAPIENTRY * PFNGLXGETFBCONFIGATTRIB) (Display*, + GLXFBConfig, + int, + int*); + PFNGLXGETFBCONFIGATTRIB xGetFBConfigAttribInternal; + + typedef void (GLAPIENTRY * PFNGLXSWAPBUFFERS) (Display*, + GLXDrawable); + PFNGLXSWAPBUFFERS xSwapBuffersInternal; + typedef const char* (GLAPIENTRY * PFNGLXQUERYEXTENSIONSSTRING) (Display*, + int); + PFNGLXQUERYEXTENSIONSSTRING xQueryExtensionsStringInternal; + typedef const char* (GLAPIENTRY * PFNGLXGETCLIENTSTRING) (Display*, + int); + PFNGLXGETCLIENTSTRING xGetClientStringInternal; + typedef const char* (GLAPIENTRY * PFNGLXQUERYSERVERSTRING) (Display*, + int, + int); + PFNGLXQUERYSERVERSTRING xQueryServerStringInternal; + + typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEPIXMAP) (Display*, + GLXFBConfig, + Pixmap, + const int*); + PFNGLXCREATEPIXMAP xCreatePixmapInternal; + typedef GLXPixmap (GLAPIENTRY * PFNGLXCREATEGLXPIXMAPWITHCONFIG) + (Display*, + GLXFBConfig, + Pixmap); + PFNGLXCREATEGLXPIXMAPWITHCONFIG xCreateGLXPixmapWithConfigInternal; + typedef void (GLAPIENTRY * PFNGLXDESTROYPIXMAP) (Display*, + GLXPixmap); + PFNGLXDESTROYPIXMAP xDestroyPixmapInternal; + typedef Bool (GLAPIENTRY * PFNGLXQUERYVERSION) (Display*, + int*, + int*); + PFNGLXQUERYVERSION xQueryVersionInternal; + + typedef void (GLAPIENTRY * PFNGLXBINDTEXIMAGE) (Display*, + GLXDrawable, + int, + const int*); + PFNGLXBINDTEXIMAGE xBindTexImageInternal; + + typedef void (GLAPIENTRY * PFNGLXRELEASETEXIMAGE) (Display*, + GLXDrawable, + int); + PFNGLXRELEASETEXIMAGE xReleaseTexImageInternal; + + typedef void (GLAPIENTRY * PFNGLXWAITGL) (); + PFNGLXWAITGL xWaitGLInternal; + + typedef void (GLAPIENTRY * PFNGLXWAITX) (); + PFNGLXWAITGL xWaitXInternal; + + typedef GLXContext (GLAPIENTRY * PFNGLXCREATECONTEXTATTRIBS) (Display*, + GLXFBConfig, + GLXContext, + Bool, + const int*); + PFNGLXCREATECONTEXTATTRIBS xCreateContextAttribsInternal; + + typedef int (GLAPIENTRY * PFNGLXGETVIDEOSYNCSGI) (unsigned int* count); + PFNGLXGETVIDEOSYNCSGI xGetVideoSyncInternal; + + typedef int (GLAPIENTRY * PFNGLXWAITVIDEOSYNCSGI) (int divisor, int remainder, unsigned int* count); + PFNGLXWAITVIDEOSYNCSGI xWaitVideoSyncInternal; + + typedef void (GLAPIENTRY * PFNGLXSWAPINTERVALEXT) (Display* dpy, GLXDrawable drawable, int interval); + PFNGLXSWAPINTERVALEXT xSwapIntervalInternal; + +#ifdef DEBUG + void BeforeGLXCall(); + void AfterGLXCall(); +#endif + + bool mInitialized; + bool mTriedInitializing; + bool mUseTextureFromPixmap; + bool mDebug; + bool mHasRobustness; + bool mHasCreateContextAttribs; + bool mHasVideoSync; + bool mIsATI; + bool mIsNVIDIA; + bool mClientIsMesa; + int mGLXMajorVersion; + int mGLXMinorVersion; + PRLibrary* mOGLLibrary; +}; + +// 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..8007fe6b13 --- /dev/null +++ b/gfx/gl/GfxTexturesReporter.cpp @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "GfxTexturesReporter.h" +#include "gfxPrefs.h" + +#ifdef MOZ_CRASHREPORTER +#include "nsExceptionHandler.h" +#endif + +using namespace mozilla; +using namespace mozilla::gl; + +NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter) + +Atomic<size_t> GfxTexturesReporter::sAmount(0); +Atomic<size_t> GfxTexturesReporter::sPeakAmount(0); +Atomic<size_t> GfxTexturesReporter::sTileWasteAmount(0); + +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 (gfxPrefs::GfxLoggingTextureUsageEnabled()) { + printf_stderr("Current texture usage: %s\n", FormatBytes(sAmount).c_str()); + } + } else { + sAmount += amount; + if (sAmount > sPeakAmount) { + sPeakAmount.exchange(sAmount); + if (gfxPrefs::GfxLoggingPeakTextureUsageEnabled()) { + printf_stderr("Peak texture usage: %s\n", FormatBytes(sPeakAmount).c_str()); + } + } + } + +#ifdef MOZ_CRASHREPORTER + CrashReporter::AnnotateTexturesSize(sAmount); +#endif +} diff --git a/gfx/gl/GfxTexturesReporter.h b/gfx/gl/GfxTexturesReporter.h new file mode 100644 index 0000000000..ed4603f0a1 --- /dev/null +++ b/gfx/gl/GfxTexturesReporter.h @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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() {} + +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..2fae79245a --- /dev/null +++ b/gfx/gl/HeapCopyOfStackArray.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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(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/ScopedGLHelpers.cpp b/gfx/gl/ScopedGLHelpers.cpp new file mode 100644 index 0000000000..fade357880 --- /dev/null +++ b/gfx/gl/ScopedGLHelpers.cpp @@ -0,0 +1,540 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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 "mozilla/UniquePtr.h" + +#include "GLContext.h" +#include "ScopedGLHelpers.h" + +namespace mozilla { +namespace gl { + +#ifdef DEBUG +bool +IsContextCurrent(GLContext* gl) +{ + return gl->IsCurrent(); +} +#endif + +/* ScopedGLState - Wraps glEnable/glDisable. **********************************/ + +// Use |newState = true| to enable, |false| to disable. +ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState) + : ScopedGLWrapper<ScopedGLState>(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) + : ScopedGLWrapper<ScopedGLState>(aGL) + , mCapability(aCapability) +{ + mOldState = mGL->fIsEnabled(mCapability); +} + +void +ScopedGLState::UnwrapImpl() +{ + 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) + : ScopedGLWrapper<ScopedBindFramebuffer>(aGL) +{ + Init(); +} + +ScopedBindFramebuffer::ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB) + : ScopedGLWrapper<ScopedBindFramebuffer>(aGL) +{ + Init(); + mGL->BindFB(aNewFB); +} + +void +ScopedBindFramebuffer::UnwrapImpl() +{ + if (mOldReadFB == mOldDrawFB) { + mGL->BindFB(mOldDrawFB); + } else { + mGL->BindDrawFB(mOldDrawFB); + mGL->BindReadFB(mOldReadFB); + } +} + + +/* ScopedBindTextureUnit ******************************************************/ + +ScopedBindTextureUnit::ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit) + : ScopedGLWrapper<ScopedBindTextureUnit>(aGL) +{ + MOZ_ASSERT(aTexUnit >= LOCAL_GL_TEXTURE0); + mGL->GetUIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &mOldTexUnit); + mGL->fActiveTexture(aTexUnit); +} + +void +ScopedBindTextureUnit::UnwrapImpl() { + mGL->fActiveTexture(mOldTexUnit); +} + + +/* ScopedTexture **************************************************************/ + +ScopedTexture::ScopedTexture(GLContext* aGL) + : ScopedGLWrapper<ScopedTexture>(aGL) +{ + mGL->fGenTextures(1, &mTexture); +} + +void +ScopedTexture::UnwrapImpl() +{ + mGL->fDeleteTextures(1, &mTexture); +} + +/* ScopedFramebuffer **************************************************************/ + +ScopedFramebuffer::ScopedFramebuffer(GLContext* aGL) + : ScopedGLWrapper<ScopedFramebuffer>(aGL) +{ + mGL->fGenFramebuffers(1, &mFB); +} + +void +ScopedFramebuffer::UnwrapImpl() +{ + mGL->fDeleteFramebuffers(1, &mFB); +} + + +/* ScopedRenderbuffer **************************************************************/ + +ScopedRenderbuffer::ScopedRenderbuffer(GLContext* aGL) + : ScopedGLWrapper<ScopedRenderbuffer>(aGL) +{ + mGL->fGenRenderbuffers(1, &mRB); +} + +void +ScopedRenderbuffer::UnwrapImpl() +{ + 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) + : ScopedGLWrapper<ScopedBindTexture>(aGL) + , mTarget(aTarget) + , mOldTex(GetBoundTexture(aGL, aTarget)) +{ + mGL->fBindTexture(mTarget, aNewTex); +} + +void +ScopedBindTexture::UnwrapImpl() +{ + mGL->fBindTexture(mTarget, mOldTex); +} + + +/* ScopedBindRenderbuffer *****************************************************/ + +void +ScopedBindRenderbuffer::Init() +{ + mOldRB = 0; + mGL->GetUIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &mOldRB); +} + +ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL) + : ScopedGLWrapper<ScopedBindRenderbuffer>(aGL) +{ + Init(); +} + +ScopedBindRenderbuffer::ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB) + : ScopedGLWrapper<ScopedBindRenderbuffer>(aGL) +{ + Init(); + mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, aNewRB); +} + +void +ScopedBindRenderbuffer::UnwrapImpl() +{ + mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, mOldRB); +} + + +/* ScopedFramebufferForTexture ************************************************/ +ScopedFramebufferForTexture::ScopedFramebufferForTexture(GLContext* aGL, + GLuint aTexture, + GLenum aTarget) + : ScopedGLWrapper<ScopedFramebufferForTexture>(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; + } +} + +void ScopedFramebufferForTexture::UnwrapImpl() +{ + if (!mFB) + return; + + mGL->fDeleteFramebuffers(1, &mFB); + mFB = 0; +} + + +/* ScopedFramebufferForRenderbuffer *******************************************/ + + +ScopedFramebufferForRenderbuffer::ScopedFramebufferForRenderbuffer(GLContext* aGL, + GLuint aRB) + : ScopedGLWrapper<ScopedFramebufferForRenderbuffer>(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; + } +} + +void +ScopedFramebufferForRenderbuffer::UnwrapImpl() +{ + if (!mFB) + return; + + mGL->fDeleteFramebuffers(1, &mFB); + mFB = 0; +} + +/* ScopedViewportRect *********************************************************/ + +ScopedViewportRect::ScopedViewportRect(GLContext* aGL, + GLint x, GLint y, + GLsizei width, GLsizei height) + : ScopedGLWrapper<ScopedViewportRect>(aGL) +{ + mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, mSavedViewportRect); + mGL->fViewport(x, y, width, height); +} + +void ScopedViewportRect::UnwrapImpl() +{ + mGL->fViewport(mSavedViewportRect[0], + mSavedViewportRect[1], + mSavedViewportRect[2], + mSavedViewportRect[3]); +} + +/* ScopedScissorRect **********************************************************/ + +ScopedScissorRect::ScopedScissorRect(GLContext* aGL, + GLint x, GLint y, + GLsizei width, GLsizei height) + : ScopedGLWrapper<ScopedScissorRect>(aGL) +{ + mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect); + mGL->fScissor(x, y, width, height); +} + +ScopedScissorRect::ScopedScissorRect(GLContext* aGL) + : ScopedGLWrapper<ScopedScissorRect>(aGL) +{ + mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, mSavedScissorRect); +} + +void ScopedScissorRect::UnwrapImpl() +{ + 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) + : ScopedGLWrapper<ScopedVertexAttribPointer>(aGL) +{ + 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) + : ScopedGLWrapper<ScopedVertexAttribPointer>(aGL) +{ + 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); +} + +void +ScopedVertexAttribPointer::UnwrapImpl() +{ + 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); +} + +ScopedGLDrawState::ScopedGLDrawState(GLContext* aGL) + : blend (aGL, LOCAL_GL_BLEND, false) + , cullFace (aGL, LOCAL_GL_CULL_FACE, false) + , depthTest (aGL, LOCAL_GL_DEPTH_TEST, false) + , dither (aGL, LOCAL_GL_DITHER, false) + , polyOffsFill(aGL, LOCAL_GL_POLYGON_OFFSET_FILL, false) + , sampleAToC (aGL, LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE, false) + , sampleCover (aGL, LOCAL_GL_SAMPLE_COVERAGE, false) + , scissor (aGL, LOCAL_GL_SCISSOR_TEST, false) + , stencil (aGL, LOCAL_GL_STENCIL_TEST, false) + , mGL(aGL) +{ + mGL->GetUIntegerv(LOCAL_GL_CURRENT_PROGRAM, &boundProgram); + mGL->GetUIntegerv(LOCAL_GL_ARRAY_BUFFER_BINDING, &boundBuffer); + mGL->GetUIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &maxAttrib); + attrib_enabled = MakeUnique<GLint[]>(maxAttrib); + + for (GLuint i = 0; i < maxAttrib; i++) { + mGL->fGetVertexAttribiv(i, LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED, &attrib_enabled[i]); + mGL->fDisableVertexAttribArray(i); + } + // Only Attrib0's client side state affected + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE, &attrib0_size); + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE, &attrib0_stride); + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE, &attrib0_type); + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &attrib0_normalized); + mGL->fGetVertexAttribiv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &attrib0_bufferBinding); + mGL->fGetVertexAttribPointerv(0, LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER, &attrib0_pointer); + mGL->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorMask); + mGL->fGetIntegerv(LOCAL_GL_VIEWPORT, viewport); + mGL->fGetIntegerv(LOCAL_GL_SCISSOR_BOX, scissorBox); +} + +ScopedGLDrawState::~ScopedGLDrawState() +{ + MOZ_ASSERT(mGL->IsCurrent()); + + mGL->fScissor(scissorBox[0], scissorBox[1], + scissorBox[2], scissorBox[3]); + + mGL->fViewport(viewport[0], viewport[1], + viewport[2], viewport[3]); + + mGL->fColorMask(colorMask[0], + colorMask[1], + colorMask[2], + colorMask[3]); + + for (unsigned int i = 0; i < maxAttrib; i++) { + if (attrib_enabled[i]) + mGL->fEnableVertexAttribArray(i); + else + mGL->fDisableVertexAttribArray(i); + } + + + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0_bufferBinding); + mGL->fVertexAttribPointer(0, + attrib0_size, + attrib0_type, + attrib0_normalized, + attrib0_stride, + attrib0_pointer); + + mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, boundBuffer); + + mGL->fUseProgram(boundProgram); +} + +//////////////////////////////////////////////////////////////////////// +// ScopedPackState + +static bool +HasPBOState(const GLContext* gl) +{ + return (!gl->IsGLES() || gl->Version() >= 300); +} + +ScopedPackState::ScopedPackState(GLContext* gl) + : ScopedGLWrapper<ScopedPackState>(gl) +{ + mGL->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mAlignment); + + if (mAlignment != 4) mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, 4); + + if (!HasPBOState(mGL)) + 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); +} + +void +ScopedPackState::UnwrapImpl() +{ + mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mAlignment); + + if (!HasPBOState(mGL)) + 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); +} + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/ScopedGLHelpers.h b/gfx/gl/ScopedGLHelpers.h new file mode 100644 index 0000000000..f0a91c69ab --- /dev/null +++ b/gfx/gl/ScopedGLHelpers.h @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 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 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 + +//RAII via CRTP! +template <class Derived> +struct ScopedGLWrapper +{ +private: + bool mIsUnwrapped; + +protected: + GLContext* const mGL; + + explicit ScopedGLWrapper(GLContext* gl) + : mIsUnwrapped(false) + , mGL(gl) + { + MOZ_ASSERT(&ScopedGLWrapper<Derived>::Unwrap == &Derived::Unwrap); + MOZ_ASSERT(&Derived::UnwrapImpl); + MOZ_ASSERT(IsContextCurrent(mGL)); + } + + virtual ~ScopedGLWrapper() { + if (!mIsUnwrapped) + Unwrap(); + } + +public: + void Unwrap() { + MOZ_ASSERT(!mIsUnwrapped); + MOZ_ASSERT(IsContextCurrent(mGL)); + + Derived* derived = static_cast<Derived*>(this); + derived->UnwrapImpl(); + + mIsUnwrapped = true; + } +}; + +// Wraps glEnable/Disable. +struct ScopedGLState + : public ScopedGLWrapper<ScopedGLState> +{ + friend struct ScopedGLWrapper<ScopedGLState>; + +protected: + 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); + +protected: + void UnwrapImpl(); +}; + +// Saves and restores with GetUserBoundFB and BindUserFB. +struct ScopedBindFramebuffer + : public ScopedGLWrapper<ScopedBindFramebuffer> +{ + friend struct ScopedGLWrapper<ScopedBindFramebuffer>; + +protected: + GLuint mOldReadFB; + GLuint mOldDrawFB; + +private: + void Init(); + +public: + explicit ScopedBindFramebuffer(GLContext* aGL); + ScopedBindFramebuffer(GLContext* aGL, GLuint aNewFB); + +protected: + void UnwrapImpl(); +}; + +struct ScopedBindTextureUnit + : public ScopedGLWrapper<ScopedBindTextureUnit> +{ + friend struct ScopedGLWrapper<ScopedBindTextureUnit>; + +protected: + GLenum mOldTexUnit; + +public: + ScopedBindTextureUnit(GLContext* aGL, GLenum aTexUnit); + +protected: + void UnwrapImpl(); +}; + + +struct ScopedTexture + : public ScopedGLWrapper<ScopedTexture> +{ + friend struct ScopedGLWrapper<ScopedTexture>; + +protected: + GLuint mTexture; + +public: + explicit ScopedTexture(GLContext* aGL); + GLuint Texture() { return mTexture; } + +protected: + void UnwrapImpl(); +}; + + +struct ScopedFramebuffer + : public ScopedGLWrapper<ScopedFramebuffer> +{ + friend struct ScopedGLWrapper<ScopedFramebuffer>; + +protected: + GLuint mFB; + +public: + explicit ScopedFramebuffer(GLContext* aGL); + GLuint FB() { return mFB; } + +protected: + void UnwrapImpl(); +}; + + +struct ScopedRenderbuffer + : public ScopedGLWrapper<ScopedRenderbuffer> +{ + friend struct ScopedGLWrapper<ScopedRenderbuffer>; + +protected: + GLuint mRB; + +public: + explicit ScopedRenderbuffer(GLContext* aGL); + GLuint RB() { return mRB; } + +protected: + void UnwrapImpl(); +}; + + +struct ScopedBindTexture + : public ScopedGLWrapper<ScopedBindTexture> +{ + friend struct ScopedGLWrapper<ScopedBindTexture>; + +protected: + const GLenum mTarget; + const GLuint mOldTex; + +public: + ScopedBindTexture(GLContext* aGL, GLuint aNewTex, + GLenum aTarget = LOCAL_GL_TEXTURE_2D); + +protected: + void UnwrapImpl(); +}; + + +struct ScopedBindRenderbuffer + : public ScopedGLWrapper<ScopedBindRenderbuffer> +{ + friend struct ScopedGLWrapper<ScopedBindRenderbuffer>; + +protected: + GLuint mOldRB; + +private: + void Init(); + +public: + explicit ScopedBindRenderbuffer(GLContext* aGL); + + ScopedBindRenderbuffer(GLContext* aGL, GLuint aNewRB); + +protected: + void UnwrapImpl(); +}; + + +struct ScopedFramebufferForTexture + : public ScopedGLWrapper<ScopedFramebufferForTexture> +{ + friend struct ScopedGLWrapper<ScopedFramebufferForTexture>; + +protected: + bool mComplete; // True if the framebuffer we create is complete. + GLuint mFB; + +public: + ScopedFramebufferForTexture(GLContext* aGL, GLuint aTexture, + GLenum aTarget = LOCAL_GL_TEXTURE_2D); + + bool IsComplete() const { + return mComplete; + } + + GLuint FB() const { + MOZ_ASSERT(IsComplete()); + return mFB; + } + +protected: + void UnwrapImpl(); +}; + +struct ScopedFramebufferForRenderbuffer + : public ScopedGLWrapper<ScopedFramebufferForRenderbuffer> +{ + friend struct ScopedGLWrapper<ScopedFramebufferForRenderbuffer>; + +protected: + bool mComplete; // True if the framebuffer we create is complete. + GLuint mFB; + +public: + ScopedFramebufferForRenderbuffer(GLContext* aGL, GLuint aRB); + + bool IsComplete() const { + return mComplete; + } + + GLuint FB() const { + return mFB; + } + +protected: + void UnwrapImpl(); +}; + +struct ScopedViewportRect + : public ScopedGLWrapper<ScopedViewportRect> +{ + friend struct ScopedGLWrapper<ScopedViewportRect>; + +protected: + GLint mSavedViewportRect[4]; + +public: + ScopedViewportRect(GLContext* aGL, GLint x, GLint y, GLsizei width, GLsizei height); + +protected: + void UnwrapImpl(); +}; + +struct ScopedScissorRect + : public ScopedGLWrapper<ScopedScissorRect> +{ + friend struct ScopedGLWrapper<ScopedScissorRect>; + +protected: + GLint mSavedScissorRect[4]; + +public: + ScopedScissorRect(GLContext* aGL, GLint x, GLint y, GLsizei width, GLsizei height); + explicit ScopedScissorRect(GLContext* aGL); + +protected: + void UnwrapImpl(); +}; + +struct ScopedVertexAttribPointer + : public ScopedGLWrapper<ScopedVertexAttribPointer> +{ + friend struct ScopedGLWrapper<ScopedVertexAttribPointer>; + +protected: + 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); + +protected: + void WrapImpl(GLuint index); + void UnwrapImpl(); +}; + +struct ScopedGLDrawState +{ + explicit ScopedGLDrawState(GLContext* gl); + ~ScopedGLDrawState(); + + GLuint boundProgram; + GLuint boundBuffer; + + ScopedGLState blend; + ScopedGLState cullFace; + ScopedGLState depthTest; + ScopedGLState dither; + ScopedGLState polyOffsFill; + ScopedGLState sampleAToC; + ScopedGLState sampleCover; + ScopedGLState scissor; + ScopedGLState stencil; + + GLuint maxAttrib; + UniquePtr<GLint[]> attrib_enabled; + GLint attrib0_size; + GLint attrib0_stride; + GLint attrib0_type; + GLint attrib0_normalized; + GLint attrib0_bufferBinding; + void* attrib0_pointer; + + realGLboolean colorMask[4]; + GLint viewport[4]; + GLint scissorBox[4]; + GLContext* const mGL; +}; + +struct ScopedPackState + : public ScopedGLWrapper<ScopedPackState> +{ + friend struct ScopedGLWrapper<ScopedPackState>; + +protected: + GLint mAlignment; + + GLuint mPixelBuffer; + GLint mRowLength; + GLint mSkipPixels; + GLint mSkipRows; + +public: + explicit ScopedPackState(GLContext* gl); + +protected: + void UnwrapImpl(); +}; + +} /* 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..fa1d19172f --- /dev/null +++ b/gfx/gl/SharedSurface.cpp @@ -0,0 +1,621 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "mozilla/layers/CompositorTypes.h" +#include "mozilla/layers/TextureClientSharedSurface.h" +#include "mozilla/layers/TextureForwarder.h" +#include "mozilla/Unused.h" + +namespace mozilla { +namespace gl { + +/*static*/ void +SharedSurface::ProdCopy(SharedSurface* src, SharedSurface* dest, + SurfaceFactory* factory) +{ + GLContext* gl = src->mGL; + + // If `src` begins locked, it must end locked, though we may + // temporarily unlock it if we need to. + MOZ_ASSERT((src == gl->GetLockedSurface()) == src->IsLocked()); + + gl->MakeCurrent(); + + if (src->mAttachType == AttachmentType::Screen && + dest->mAttachType == AttachmentType::Screen) + { + // Here, we actually need to blit through a temp surface, so let's make one. + UniquePtr<SharedSurface_Basic> tempSurf; + tempSurf = SharedSurface_Basic::Create(gl, factory->mFormats, src->mSize, + factory->mCaps.alpha); + + ProdCopy(src, tempSurf.get(), factory); + ProdCopy(tempSurf.get(), dest, factory); + return; + } + + if (src->mAttachType == AttachmentType::Screen) { + SharedSurface* origLocked = gl->GetLockedSurface(); + bool srcNeedsUnlock = false; + bool origNeedsRelock = false; + if (origLocked != src) { + if (origLocked) { + origLocked->UnlockProd(); + origNeedsRelock = true; + } + + src->LockProd(); + srcNeedsUnlock = true; + } + + if (dest->mAttachType == AttachmentType::GLTexture) { + GLuint destTex = dest->ProdTexture(); + GLenum destTarget = dest->ProdTextureTarget(); + + gl->BlitHelper()->BlitFramebufferToTexture(0, destTex, + src->mSize, + dest->mSize, + destTarget, + true); + } else if (dest->mAttachType == AttachmentType::GLRenderbuffer) { + GLuint destRB = dest->ProdRenderbuffer(); + ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); + + gl->BlitHelper()->BlitFramebufferToFramebuffer(0, + destWrapper.FB(), + src->mSize, + dest->mSize, + true); + } else { + MOZ_CRASH("GFX: Unhandled dest->mAttachType 1."); + } + + if (srcNeedsUnlock) + src->UnlockProd(); + + if (origNeedsRelock) + origLocked->LockProd(); + + return; + } + + if (dest->mAttachType == AttachmentType::Screen) { + SharedSurface* origLocked = gl->GetLockedSurface(); + bool destNeedsUnlock = false; + bool origNeedsRelock = false; + if (origLocked != dest) { + if (origLocked) { + origLocked->UnlockProd(); + origNeedsRelock = true; + } + + dest->LockProd(); + destNeedsUnlock = true; + } + + if (src->mAttachType == AttachmentType::GLTexture) { + GLuint srcTex = src->ProdTexture(); + GLenum srcTarget = src->ProdTextureTarget(); + + gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, 0, + src->mSize, + dest->mSize, + srcTarget, + true); + } else if (src->mAttachType == AttachmentType::GLRenderbuffer) { + GLuint srcRB = src->ProdRenderbuffer(); + ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); + + gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), + 0, + src->mSize, + dest->mSize, + true); + } else { + MOZ_CRASH("GFX: Unhandled src->mAttachType 2."); + } + + if (destNeedsUnlock) + dest->UnlockProd(); + + if (origNeedsRelock) + origLocked->LockProd(); + + return; + } + + // Alright, done with cases involving Screen types. + // Only {src,dest}x{texture,renderbuffer} left. + + if (src->mAttachType == AttachmentType::GLTexture) { + GLuint srcTex = src->ProdTexture(); + GLenum srcTarget = src->ProdTextureTarget(); + + if (dest->mAttachType == AttachmentType::GLTexture) { + GLuint destTex = dest->ProdTexture(); + GLenum destTarget = dest->ProdTextureTarget(); + + gl->BlitHelper()->BlitTextureToTexture(srcTex, destTex, + src->mSize, dest->mSize, + srcTarget, destTarget); + + return; + } + + if (dest->mAttachType == AttachmentType::GLRenderbuffer) { + GLuint destRB = dest->ProdRenderbuffer(); + ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); + + gl->BlitHelper()->BlitTextureToFramebuffer(srcTex, destWrapper.FB(), + src->mSize, dest->mSize, srcTarget); + + return; + } + + MOZ_CRASH("GFX: Unhandled dest->mAttachType 3."); + } + + if (src->mAttachType == AttachmentType::GLRenderbuffer) { + GLuint srcRB = src->ProdRenderbuffer(); + ScopedFramebufferForRenderbuffer srcWrapper(gl, srcRB); + + if (dest->mAttachType == AttachmentType::GLTexture) { + GLuint destTex = dest->ProdTexture(); + GLenum destTarget = dest->ProdTextureTarget(); + + gl->BlitHelper()->BlitFramebufferToTexture(srcWrapper.FB(), destTex, + src->mSize, dest->mSize, destTarget); + + return; + } + + if (dest->mAttachType == AttachmentType::GLRenderbuffer) { + GLuint destRB = dest->ProdRenderbuffer(); + ScopedFramebufferForRenderbuffer destWrapper(gl, destRB); + + gl->BlitHelper()->BlitFramebufferToFramebuffer(srcWrapper.FB(), destWrapper.FB(), + src->mSize, dest->mSize); + + return; + } + + MOZ_CRASH("GFX: Unhandled dest->mAttachType 4."); + } + + MOZ_CRASH("GFX: Unhandled src->mAttachType 5."); +} + +//////////////////////////////////////////////////////////////////////// +// SharedSurface + + +SharedSurface::SharedSurface(SharedSurfaceType type, + AttachmentType attachType, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + bool canRecycle) + : mType(type) + , mAttachType(attachType) + , mGL(gl) + , mSize(size) + , mHasAlpha(hasAlpha) + , mCanRecycle(canRecycle) + , mIsLocked(false) + , mIsProducerAcquired(false) +#ifdef DEBUG + , mOwningThread(NS_GetCurrentThread()) +#endif +{ } + +layers::TextureFlags +SharedSurface::GetTextureFlags() const +{ + return layers::TextureFlags::NO_FLAGS; +} + +void +SharedSurface::LockProd() +{ + MOZ_ASSERT(!mIsLocked); + + LockProdImpl(); + + mGL->LockSurface(this); + mIsLocked = true; +} + +void +SharedSurface::UnlockProd() +{ + if (!mIsLocked) + return; + + UnlockProdImpl(); + + mGL->UnlockSurface(this); + mIsLocked = false; +} + +//////////////////////////////////////////////////////////////////////// +// SurfaceFactory + +static void +ChooseBufferBits(const SurfaceCaps& caps, + SurfaceCaps* const out_drawCaps, + SurfaceCaps* const out_readCaps) +{ + MOZ_ASSERT(out_drawCaps); + MOZ_ASSERT(out_readCaps); + + SurfaceCaps screenCaps; + + screenCaps.color = caps.color; + screenCaps.alpha = caps.alpha; + screenCaps.bpp16 = caps.bpp16; + + screenCaps.depth = caps.depth; + screenCaps.stencil = caps.stencil; + + screenCaps.antialias = caps.antialias; + screenCaps.preserve = caps.preserve; + + if (caps.antialias) { + *out_drawCaps = screenCaps; + out_readCaps->Clear(); + + // Color caps need to be duplicated in readCaps. + out_readCaps->color = caps.color; + out_readCaps->alpha = caps.alpha; + out_readCaps->bpp16 = caps.bpp16; + } else { + out_drawCaps->Clear(); + *out_readCaps = screenCaps; + } +} + +SurfaceFactory::SurfaceFactory(SharedSurfaceType type, GLContext* gl, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) + : mType(type) + , mGL(gl) + , mCaps(caps) + , mAllocator(allocator) + , mFlags(flags) + , mFormats(gl->ChooseGLFormats(caps)) + , mMutex("SurfaceFactor::mMutex") +{ + ChooseBufferBits(mCaps, &mDrawCaps, &mReadCaps); +} + +SurfaceFactory::~SurfaceFactory() +{ + while (!mRecycleTotalPool.empty()) { + RefPtr<layers::SharedSurfaceTextureClient> tex = *mRecycleTotalPool.begin(); + StopRecycling(tex); + tex->CancelWaitForRecycle(); + } + + MOZ_RELEASE_ASSERT(mRecycleTotalPool.empty(),"GFX: Surface recycle pool not empty."); + + // If we mRecycleFreePool.clear() before StopRecycling(), we may try to recycle it, + // fail, call StopRecycling(), then return here and call it again. + mRecycleFreePool.clear(); +} + +already_AddRefed<layers::SharedSurfaceTextureClient> +SurfaceFactory::NewTexClient(const gfx::IntSize& size) +{ + while (!mRecycleFreePool.empty()) { + RefPtr<layers::SharedSurfaceTextureClient> cur = mRecycleFreePool.front(); + mRecycleFreePool.pop(); + + if (cur->Surf()->mSize == size) { + cur->Surf()->WaitForBufferOwnership(); + return cur.forget(); + } + + StopRecycling(cur); + } + + UniquePtr<SharedSurface> surf = Move(CreateShared(size)); + if (!surf) + return nullptr; + + RefPtr<layers::SharedSurfaceTextureClient> ret; + ret = layers::SharedSurfaceTextureClient::Create(Move(surf), this, mAllocator, mFlags); + + StartRecycling(ret); + + return ret.forget(); +} + +void +SurfaceFactory::StartRecycling(layers::SharedSurfaceTextureClient* tc) +{ + tc->SetRecycleCallback(&SurfaceFactory::RecycleCallback, static_cast<void*>(this)); + + bool didInsert = mRecycleTotalPool.insert(tc); + MOZ_RELEASE_ASSERT(didInsert, "GFX: Shared surface texture client was not inserted to recycle."); + mozilla::Unused << didInsert; +} + +void +SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc) +{ + MutexAutoLock autoLock(mMutex); + // Must clear before releasing ref. + tc->ClearRecycleCallback(); + + bool didErase = mRecycleTotalPool.erase(tc); + MOZ_RELEASE_ASSERT(didErase, "GFX: Shared texture surface client was not erased."); + mozilla::Unused << didErase; +} + +/*static*/ void +SurfaceFactory::RecycleCallback(layers::TextureClient* rawTC, void* rawFactory) +{ + RefPtr<layers::SharedSurfaceTextureClient> tc; + tc = static_cast<layers::SharedSurfaceTextureClient*>(rawTC); + SurfaceFactory* factory = static_cast<SurfaceFactory*>(rawFactory); + + if (tc->Surf()->mCanRecycle) { + if (factory->Recycle(tc)) + return; + } + + // Did not recover the tex client. End the (re)cycle! + factory->StopRecycling(tc); +} + +bool +SurfaceFactory::Recycle(layers::SharedSurfaceTextureClient* texClient) +{ + MOZ_ASSERT(texClient); + MutexAutoLock autoLock(mMutex); + + if (mRecycleFreePool.size() >= 2) { + return false; + } + + RefPtr<layers::SharedSurfaceTextureClient> texClientRef = texClient; + mRecycleFreePool.push(texClientRef); + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// ScopedReadbackFB + +ScopedReadbackFB::ScopedReadbackFB(SharedSurface* src) + : mGL(src->mGL) + , mAutoFB(mGL) + , mTempFB(0) + , mTempTex(0) + , mSurfToUnlock(nullptr) + , mSurfToLock(nullptr) +{ + switch (src->mAttachType) { + case AttachmentType::GLRenderbuffer: + { + mGL->fGenFramebuffers(1, &mTempFB); + mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB); + + GLuint rb = src->ProdRenderbuffer(); + mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_RENDERBUFFER, rb); + break; + } + case AttachmentType::GLTexture: + { + mGL->fGenFramebuffers(1, &mTempFB); + mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB); + + GLuint tex = src->ProdTexture(); + GLenum texImageTarget = src->ProdTextureTarget(); + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + texImageTarget, tex, 0); + break; + } + case AttachmentType::Screen: + { + SharedSurface* origLocked = mGL->GetLockedSurface(); + if (origLocked != src) { + if (origLocked) { + mSurfToLock = origLocked; + mSurfToLock->UnlockProd(); + } + + mSurfToUnlock = src; + mSurfToUnlock->LockProd(); + } + + // TODO: This should just be BindFB, but we don't have + // the patch for this yet. (bug 1045955) + MOZ_ASSERT(mGL->Screen()); + mGL->Screen()->BindReadFB_Internal(0); + break; + } + default: + MOZ_CRASH("GFX: Unhandled `mAttachType`."); + } + + if (src->NeedsIndirectReads()) { + mGL->fGenTextures(1, &mTempTex); + + { + ScopedBindTexture autoTex(mGL, mTempTex); + + GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA + : LOCAL_GL_RGB; + auto width = src->mSize.width; + auto height = src->mSize.height; + mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width, + height, 0); + } + + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, mTempTex, 0); + } +} + +ScopedReadbackFB::~ScopedReadbackFB() +{ + if (mTempFB) { + mGL->fDeleteFramebuffers(1, &mTempFB); + } + if (mTempTex) { + mGL->fDeleteTextures(1, &mTempTex); + } + if (mSurfToUnlock) { + mSurfToUnlock->UnlockProd(); + } + if (mSurfToLock) { + mSurfToLock->LockProd(); + } +} + +//////////////////////////////////////////////////////////////////////////////// + +class AutoLockBits +{ + gfx::DrawTarget* mDT; + uint8_t* mLockedBits; + +public: + explicit AutoLockBits(gfx::DrawTarget* dt) + : mDT(dt) + , mLockedBits(nullptr) + { + MOZ_ASSERT(mDT); + } + + bool Lock(uint8_t** data, gfx::IntSize* size, int32_t* stride, + gfx::SurfaceFormat* format) + { + if (!mDT->LockBits(data, size, stride, format)) + return false; + + mLockedBits = *data; + return true; + } + + ~AutoLockBits() { + if (mLockedBits) + mDT->ReleaseBits(mLockedBits); + } +}; + +bool +ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst) +{ + AutoLockBits lock(dst); + + uint8_t* dstBytes; + gfx::IntSize dstSize; + int32_t dstStride; + gfx::SurfaceFormat dstFormat; + if (!lock.Lock(&dstBytes, &dstSize, &dstStride, &dstFormat)) + return false; + + const bool isDstRGBA = (dstFormat == gfx::SurfaceFormat::R8G8B8A8 || + dstFormat == gfx::SurfaceFormat::R8G8B8X8); + MOZ_ASSERT_IF(!isDstRGBA, dstFormat == gfx::SurfaceFormat::B8G8R8A8 || + dstFormat == gfx::SurfaceFormat::B8G8R8X8); + + size_t width = src->mSize.width; + size_t height = src->mSize.height; + MOZ_ASSERT(width == (size_t)dstSize.width); + MOZ_ASSERT(height == (size_t)dstSize.height); + + GLenum readGLFormat; + GLenum readType; + + { + ScopedReadbackFB autoReadback(src); + + + // We have a source FB, now we need a format. + GLenum dstGLFormat = isDstRGBA ? LOCAL_GL_BGRA : LOCAL_GL_RGBA; + GLenum dstType = LOCAL_GL_UNSIGNED_BYTE; + + // We actually don't care if they match, since we can handle + // any read{Format,Type} we get. + GLContext* gl = src->mGL; + GetActualReadFormats(gl, dstGLFormat, dstType, &readGLFormat, + &readType); + + MOZ_ASSERT(readGLFormat == LOCAL_GL_RGBA || + readGLFormat == LOCAL_GL_BGRA); + MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE); + + // ReadPixels from the current FB into lockedBits. + { + size_t alignment = 8; + if (dstStride % 4 == 0) + alignment = 4; + + ScopedPackState scopedPackState(gl); + if (alignment != 4) { + gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, alignment); + } + + gl->raw_fReadPixels(0, 0, width, height, readGLFormat, readType, + dstBytes); + } + } + + const bool isReadRGBA = readGLFormat == LOCAL_GL_RGBA; + + if (isReadRGBA != isDstRGBA) { + for (size_t j = 0; j < height; ++j) { + uint8_t* rowItr = dstBytes + j*dstStride; + uint8_t* rowEnd = rowItr + 4*width; + while (rowItr != rowEnd) { + Swap(rowItr[0], rowItr[2]); + rowItr += 4; + } + } + } + + return true; +} + +uint32_t +ReadPixel(SharedSurface* src) +{ + GLContext* gl = src->mGL; + + uint32_t pixel; + + ScopedReadbackFB a(src); + { + ScopedPackState scopedPackState(gl); + + UniquePtr<uint8_t[]> bytes(new uint8_t[4]); + gl->raw_fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, + bytes.get()); + memcpy(&pixel, bytes.get(), 4); + } + + return pixel; +} + +} // namespace gl + +} /* namespace mozilla */ diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h new file mode 100644 index 0000000000..0cd21d1b7b --- /dev/null +++ b/gfx/gl/SharedSurface.h @@ -0,0 +1,333 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "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 "ScopedGLHelpers.h" +#include "SurfaceTypes.h" + +class nsIThread; + +namespace mozilla { +namespace gfx { +class DataSourceSurface; +class DrawTarget; +} // namespace gfx + +namespace layers { +class LayersIPCChannel; +class SharedSurfaceTextureClient; +enum class TextureFlags : uint32_t; +class SurfaceDescriptor; +class TextureClient; +} // namespace layers + +namespace gl { + +class GLContext; +class SurfaceFactory; +class ShSurfHandle; + +class SharedSurface +{ +public: + static void ProdCopy(SharedSurface* src, SharedSurface* dest, + SurfaceFactory* factory); + + const SharedSurfaceType mType; + const AttachmentType mAttachType; + const WeakPtr<GLContext> mGL; + const gfx::IntSize mSize; + const bool mHasAlpha; + const bool mCanRecycle; +protected: + bool mIsLocked; + bool mIsProducerAcquired; +#ifdef DEBUG + nsIThread* const mOwningThread; +#endif + + SharedSurface(SharedSurfaceType type, + AttachmentType attachType, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + bool canRecycle); + +public: + virtual ~SharedSurface() { + } + + // Specifies to the TextureClient any flags which + // are required by the SharedSurface backend. + virtual layers::TextureFlags GetTextureFlags() const; + + 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(); + +protected: + virtual void LockProdImpl() = 0; + virtual void UnlockProdImpl() = 0; + + virtual void ProducerAcquireImpl() = 0; + virtual void ProducerReleaseImpl() = 0; + 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() {} + + // For use when AttachType is correct. + virtual GLenum ProdTextureTarget() const { + MOZ_ASSERT(mAttachType == AttachmentType::GLTexture); + return LOCAL_GL_TEXTURE_2D; + } + + virtual GLuint ProdTexture() { + MOZ_ASSERT(mAttachType == AttachmentType::GLTexture); + MOZ_CRASH("GFX: Did you forget to override this function?"); + } + + virtual GLuint ProdRenderbuffer() { + MOZ_ASSERT(mAttachType == AttachmentType::GLRenderbuffer); + MOZ_CRASH("GFX: Did you forget to override this function?"); + } + + virtual bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, + GLint y, GLsizei width, GLsizei height, GLint border) + { + return false; + } + + virtual bool ReadPixels(GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid* pixels) + { + return false; + } + + virtual bool NeedsIndirectReads() const { + return false; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) { + return false; + } +}; + +template<typename T> +class RefSet +{ + std::set<T*> mSet; + +public: + ~RefSet() { + clear(); + } + + auto begin() -> decltype(mSet.begin()) { + return mSet.begin(); + } + + void clear() { + for (auto itr = mSet.begin(); itr != mSet.end(); ++itr) { + (*itr)->Release(); + } + mSet.clear(); + } + + bool empty() const { + return mSet.empty(); + } + + bool insert(T* x) { + if (mSet.insert(x).second) { + x->AddRef(); + return true; + } + + return false; + } + + bool erase(T* x) { + if (mSet.erase(x)) { + x->Release(); + return true; + } + + return false; + } +}; + +template<typename T> +class RefQueue +{ + std::queue<T*> mQueue; + +public: + ~RefQueue() { + clear(); + } + + void clear() { + while (!empty()) { + pop(); + } + } + + bool empty() const { + return mQueue.empty(); + } + + size_t size() const { + return mQueue.size(); + } + + void push(T* x) { + mQueue.push(x); + x->AddRef(); + } + + T* front() const { + return mQueue.front(); + } + + void pop() { + T* x = mQueue.front(); + x->Release(); + mQueue.pop(); + } +}; + +class SurfaceFactory : public SupportsWeakPtr<SurfaceFactory> +{ +public: + // Should use the VIRTUAL version, but it's currently incompatible + // with SupportsWeakPtr. (bug 1049278) + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SurfaceFactory) + + const SharedSurfaceType mType; + GLContext* const mGL; + const SurfaceCaps mCaps; + const RefPtr<layers::LayersIPCChannel> mAllocator; + const layers::TextureFlags mFlags; + const GLFormats mFormats; + Mutex mMutex; +protected: + SurfaceCaps mDrawCaps; + SurfaceCaps mReadCaps; + RefQueue<layers::SharedSurfaceTextureClient> mRecycleFreePool; + RefSet<layers::SharedSurfaceTextureClient> mRecycleTotalPool; + + SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); + +public: + virtual ~SurfaceFactory(); + + const SurfaceCaps& DrawCaps() const { + return mDrawCaps; + } + + const SurfaceCaps& ReadCaps() const { + return mReadCaps; + } + +protected: + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) = 0; + + void StartRecycling(layers::SharedSurfaceTextureClient* tc); + void SetRecycleCallback(layers::SharedSurfaceTextureClient* tc); + void StopRecycling(layers::SharedSurfaceTextureClient* tc); + +public: + UniquePtr<SharedSurface> NewSharedSurface(const gfx::IntSize& size); + //already_AddRefed<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size); + already_AddRefed<layers::SharedSurfaceTextureClient> NewTexClient(const gfx::IntSize& size); + + static void RecycleCallback(layers::TextureClient* tc, void* /*closure*/); + + // Auto-deletes surfs of the wrong type. + bool Recycle(layers::SharedSurfaceTextureClient* texClient); +}; + +class ScopedReadbackFB +{ + GLContext* const mGL; + ScopedBindFramebuffer mAutoFB; + GLuint mTempFB; + GLuint mTempTex; + SharedSurface* mSurfToUnlock; + SharedSurface* mSurfToLock; + +public: + explicit ScopedReadbackFB(SharedSurface* src); + ~ScopedReadbackFB(); +}; + +bool ReadbackSharedSurface(SharedSurface* src, gfx::DrawTarget* dst); +uint32_t ReadPixel(SharedSurface* src); + +} // 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..e82a24dfd2 --- /dev/null +++ b/gfx/gl/SharedSurfaceANGLE.cpp @@ -0,0 +1,354 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc + +namespace mozilla { +namespace gl { + +// Returns `EGL_NO_SURFACE` (`0`) on error. +static EGLSurface +CreatePBufferSurface(GLLibraryEGL* egl, + EGLDisplay display, + EGLConfig config, + const gfx::IntSize& size) +{ + auto width = size.width; + auto height = size.height; + + EGLint attribs[] = { + LOCAL_EGL_WIDTH, width, + LOCAL_EGL_HEIGHT, height, + LOCAL_EGL_NONE + }; + + DebugOnly<EGLint> preCallErr = egl->fGetError(); + MOZ_ASSERT(preCallErr == LOCAL_EGL_SUCCESS); + EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs); + EGLint err = egl->fGetError(); + if (err != LOCAL_EGL_SUCCESS) + return 0; + + return surface; +} + +/*static*/ UniquePtr<SharedSurface_ANGLEShareHandle> +SharedSurface_ANGLEShareHandle::Create(GLContext* gl, EGLConfig config, + const gfx::IntSize& size, bool hasAlpha) +{ + GLLibraryEGL* egl = &sEGLLibrary; + MOZ_ASSERT(egl); + MOZ_ASSERT(egl->IsExtensionSupported( + GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle)); + MOZ_ASSERT(config); + + EGLDisplay display = egl->Display(); + EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, size); + if (!pbuffer) + return nullptr; + + // Declare everything before 'goto's. + HANDLE shareHandle = nullptr; + bool ok = egl->fQuerySurfacePointerANGLE(display, + pbuffer, + LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, + &shareHandle); + if (!ok) { + egl->fDestroySurface(egl->Display(), pbuffer); + return nullptr; + } + void* opaqueKeyedMutex = nullptr; + egl->fQuerySurfacePointerANGLE(display, + pbuffer, + LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE, + &opaqueKeyedMutex); + RefPtr<IDXGIKeyedMutex> keyedMutex = static_cast<IDXGIKeyedMutex*>(opaqueKeyedMutex); + + typedef SharedSurface_ANGLEShareHandle ptrT; + UniquePtr<ptrT> ret( new ptrT(gl, egl, size, hasAlpha, pbuffer, shareHandle, + keyedMutex) ); + return Move(ret); +} + +EGLDisplay +SharedSurface_ANGLEShareHandle::Display() +{ + return mEGL->Display(); +} + +SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(GLContext* gl, + GLLibraryEGL* egl, + const gfx::IntSize& size, + bool hasAlpha, + EGLSurface pbuffer, + HANDLE shareHandle, + const RefPtr<IDXGIKeyedMutex>& keyedMutex) + : SharedSurface(SharedSurfaceType::EGLSurfaceANGLE, + AttachmentType::Screen, + gl, + size, + hasAlpha, + true) + , mEGL(egl) + , mPBuffer(pbuffer) + , mShareHandle(shareHandle) + , mKeyedMutex(keyedMutex) +{ +} + + +SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() +{ + mEGL->fDestroySurface(Display(), mPBuffer); +} + +void +SharedSurface_ANGLEShareHandle::LockProdImpl() +{ + GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mPBuffer); +} + +void +SharedSurface_ANGLEShareHandle::UnlockProdImpl() +{ +} + +void +SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() +{ + if (mKeyedMutex) { + HRESULT hr = mKeyedMutex->AcquireSync(0, 10000); + if (hr == WAIT_TIMEOUT) { + MOZ_CRASH("GFX: ANGLE share handle timeout"); + } + } +} + +void +SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() +{ + if (mKeyedMutex) { + // 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 + mGL->fFlush(); + mKeyedMutex->ReleaseSync(0); + return; + } + mGL->fFinish(); +} + +void +SharedSurface_ANGLEShareHandle::ProducerReadAcquireImpl() +{ + ProducerAcquireImpl(); +} + +void +SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() +{ + if (mKeyedMutex) { + mKeyedMutex->ReleaseSync(0); + return; + } +} + +bool +SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 + : gfx::SurfaceFormat::B8G8R8X8; + *out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)mShareHandle, format, + mSize); + return true; +} + +class ScopedLockTexture final +{ +public: + explicit ScopedLockTexture(ID3D11Texture2D* texture, bool* succeeded) + : mIsLocked(false) + , mTexture(texture) + { + MOZ_ASSERT(NS_IsMainThread(), "Must be on the main thread to use d3d11 immediate context"); + MOZ_ASSERT(mTexture); + MOZ_ASSERT(succeeded); + *succeeded = false; + + HRESULT hr; + mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mMutex)); + if (mMutex) { + hr = mMutex->AcquireSync(0, 10000); + if (hr == WAIT_TIMEOUT) { + MOZ_CRASH("GFX: ANGLE scoped lock timeout"); + } + + if (FAILED(hr)) { + NS_WARNING("Failed to lock the texture"); + return; + } + } + + RefPtr<ID3D11Device> device = + gfx::DeviceManagerDx::Get()->GetContentDevice(); + if (!device) { + return; + } + + device->GetImmediateContext(getter_AddRefs(mDeviceContext)); + + mTexture->GetDesc(&mDesc); + mDesc.BindFlags = 0; + mDesc.Usage = D3D11_USAGE_STAGING; + mDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + mDesc.MiscFlags = 0; + + hr = device->CreateTexture2D(&mDesc, nullptr, getter_AddRefs(mCopiedTexture)); + + if (FAILED(hr)) { + return; + } + + mDeviceContext->CopyResource(mCopiedTexture, mTexture); + + hr = mDeviceContext->Map(mCopiedTexture, 0, D3D11_MAP_READ, 0, &mSubresource); + if (FAILED(hr)) { + return; + } + + *succeeded = true; + mIsLocked = true; + } + + ~ScopedLockTexture() + { + mDeviceContext->Unmap(mCopiedTexture, 0); + if (mMutex) { + HRESULT hr = mMutex->ReleaseSync(0); + if (FAILED(hr)) { + NS_WARNING("Failed to unlock the texture"); + } + } + mIsLocked = false; + } + + bool mIsLocked; + RefPtr<ID3D11Texture2D> mTexture; + RefPtr<ID3D11Texture2D> mCopiedTexture; + RefPtr<IDXGIKeyedMutex> mMutex; + RefPtr<ID3D11DeviceContext> mDeviceContext; + D3D11_TEXTURE2D_DESC mDesc; + D3D11_MAPPED_SUBRESOURCE mSubresource; +}; + +bool +SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) +{ + MOZ_ASSERT(out_surface); + + RefPtr<ID3D11Device> device = + gfx::DeviceManagerDx::Get()->GetContentDevice(); + if (!device) { + return false; + } + + RefPtr<ID3D11Texture2D> tex; + HRESULT hr = device->OpenSharedResource(mShareHandle, + __uuidof(ID3D11Texture2D), + (void**)(ID3D11Texture2D**)getter_AddRefs(tex)); + + if (FAILED(hr)) { + return false; + } + + bool succeeded = false; + ScopedLockTexture scopedLock(tex, &succeeded); + if (!succeeded) { + return false; + } + + const uint8_t* data = reinterpret_cast<uint8_t*>(scopedLock.mSubresource.pData); + uint32_t srcStride = scopedLock.mSubresource.RowPitch; + + gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE); + if (!map.IsMapped()) { + return false; + } + + if (map.GetStride() == srcStride) { + memcpy(map.GetData(), data, out_surface->GetSize().height * map.GetStride()); + } else { + const uint8_t bytesPerPixel = BytesPerPixel(out_surface->GetFormat()); + for (int32_t i = 0; i < out_surface->GetSize().height; i++) { + memcpy(map.GetData() + i * map.GetStride(), + data + i * srcStride, + bytesPerPixel * out_surface->GetSize().width); + } + } + + DXGI_FORMAT srcFormat = scopedLock.mDesc.Format; + MOZ_ASSERT(srcFormat == DXGI_FORMAT_B8G8R8A8_UNORM || + srcFormat == DXGI_FORMAT_B8G8R8X8_UNORM || + srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM); + bool isSrcRGB = srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM; + + gfx::SurfaceFormat destFormat = out_surface->GetFormat(); + MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 || + destFormat == gfx::SurfaceFormat::R8G8B8A8 || + destFormat == gfx::SurfaceFormat::B8G8R8X8 || + destFormat == gfx::SurfaceFormat::B8G8R8A8); + bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 || + destFormat == gfx::SurfaceFormat::R8G8B8A8; + + if (isSrcRGB != isDestRGB) { + SwapRAndBComponents(out_surface); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// Factory + +/*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle> +SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) +{ + GLLibraryEGL* egl = &sEGLLibrary; + if (!egl) + return nullptr; + + auto ext = GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle; + if (!egl->IsExtensionSupported(ext)) + return nullptr; + + EGLConfig config = GLContextEGL::Cast(gl)->mConfig; + + typedef SurfaceFactory_ANGLEShareHandle ptrT; + UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, egl, config) ); + return Move(ret); +} + +SurfaceFactory_ANGLEShareHandle::SurfaceFactory_ANGLEShareHandle(GLContext* gl, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags, + GLLibraryEGL* egl, + EGLConfig config) + : SurfaceFactory(SharedSurfaceType::EGLSurfaceANGLE, gl, caps, allocator, flags) + , mProdGL(gl) + , mEGL(egl) + , mConfig(config) +{ } + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h new file mode 100644 index 0000000000..5e7fe32f34 --- /dev/null +++ b/gfx/gl/SharedSurfaceANGLE.h @@ -0,0 +1,101 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "SharedSurface.h" + +struct IDXGIKeyedMutex; +struct ID3D11Texture2D; + +namespace mozilla { +namespace gl { + +class GLContext; +class GLLibraryEGL; + +class SharedSurface_ANGLEShareHandle + : public SharedSurface +{ +public: + static UniquePtr<SharedSurface_ANGLEShareHandle> Create(GLContext* gl, + EGLConfig config, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_ANGLEShareHandle* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::EGLSurfaceANGLE); + + return (SharedSurface_ANGLEShareHandle*)surf; + } + +protected: + GLLibraryEGL* const mEGL; + const EGLSurface mPBuffer; +public: + const HANDLE mShareHandle; +protected: + RefPtr<IDXGIKeyedMutex> mKeyedMutex; + + SharedSurface_ANGLEShareHandle(GLContext* gl, + GLLibraryEGL* egl, + const gfx::IntSize& size, + bool hasAlpha, + EGLSurface pbuffer, + HANDLE shareHandle, + const RefPtr<IDXGIKeyedMutex>& keyedMutex); + + EGLDisplay Display(); + +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; + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override; +}; + + + +class SurfaceFactory_ANGLEShareHandle + : public SurfaceFactory +{ +protected: + GLContext* const mProdGL; + GLLibraryEGL* const mEGL; + const EGLConfig mConfig; + +public: + static UniquePtr<SurfaceFactory_ANGLEShareHandle> Create(GLContext* gl, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); + +protected: + SurfaceFactory_ANGLEShareHandle(GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags, GLLibraryEGL* egl, + EGLConfig config); + + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_ANGLEShareHandle::Create(mProdGL, mConfig, size, hasAlpha); + } +}; + +} /* namespace gfx */ +} /* namespace mozilla */ + +#endif /* SHARED_SURFACE_ANGLE_H_ */ diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp new file mode 100644 index 0000000000..e667005d83 --- /dev/null +++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp @@ -0,0 +1,425 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "gfxPrefs.h" +#include "GLContext.h" +#include "WGLLibrary.h" +#include "nsPrintfCString.h" +#include "mozilla/gfx/DeviceManagerDx.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 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; + + 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; + + const auto interopDevice = wgl->fDXOpenDevice(d3d); + if (!interopDevice) { + gfxCriticalNote << "DXInterop2Device::Open: DXOpenDevice failed."; + return nullptr; + } + + return MakeAndAddRef<DXInterop2Device>(wgl, d3d, interopDevice, gl); + } + + DXInterop2Device(WGLLibrary* wgl, ID3D11Device* d3d, HANDLE interopDevice, + GLContext* gl) + : mWGL(wgl) + , mD3D(d3d) + , mInteropDevice(interopDevice) + , mGL(gl) + { } + + ~DXInterop2Device() { + const auto isCurrent = mGL->MakeCurrent(); + + if (mWGL->fDXCloseDevice(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 auto ret = mWGL->fDXRegisterObject(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(); + + if (mWGL->fDXUnregisterObject(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->fDXLockObjects(mInteropDevice, 1, &lockHandle)) + return true; + + if (!mGL->MakeCurrent()) + return false; + + gfxCriticalNote << "wglDXLockObjects called without mGL being current." + << " Retrying after MakeCurrent."; + + if (mWGL->fDXLockObjects(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->fDXUnlockObjects(mInteropDevice, 1, &lockHandle)) + return true; + + if (!mGL->MakeCurrent()) + return false; + + gfxCriticalNote << "wglDXUnlockObjects called without mGL being current." + << " Retrying after MakeCurrent."; + + if (mWGL->fDXUnlockObjects(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(DXInterop2Device* interop, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha) +{ + const auto& d3d = interop->mD3D; + + // Create a texture in case we need to readback. + DXGI_FORMAT format = hasAlpha ? DXGI_FORMAT_B8G8R8A8_UNORM + : DXGI_FORMAT_B8G8R8X8_UNORM; + CD3D11_TEXTURE2D_DESC desc(format, size.width, size.height, 1, 1); + desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; + + RefPtr<ID3D11Texture2D> texD3D; + auto hr = d3d->CreateTexture2D(&desc, nullptr, getter_AddRefs(texD3D)); + if (FAILED(hr)) { + NS_WARNING("Failed to create texture for CanvasLayer!"); + return nullptr; + } + + RefPtr<IDXGIResource> texDXGI; + hr = texD3D->QueryInterface(__uuidof(IDXGIResource), getter_AddRefs(texDXGI)); + if (FAILED(hr)) { + NS_WARNING("Failed to open texture for sharing!"); + return nullptr; + } + + HANDLE dxgiHandle; + texDXGI->GetSharedHandle(&dxgiHandle); + + //// + + if (!gl->MakeCurrent()) { + NS_WARNING("MakeCurrent failed."); + return nullptr; + } + + GLuint rbGL = 0; + gl->fGenRenderbuffers(1, &rbGL); + const auto lockHandle = interop->RegisterObject(texD3D, rbGL, LOCAL_GL_RENDERBUFFER, + LOCAL_WGL_ACCESS_WRITE_DISCARD_NV); + if (!lockHandle) { + NS_WARNING("Failed to register D3D object with WGL."); + gl->fDeleteRenderbuffers(1, &rbGL); + return nullptr; + } + + //// + + typedef SharedSurface_D3D11Interop ptrT; + UniquePtr<ptrT> ret ( new ptrT(gl, size, hasAlpha, rbGL, interop, lockHandle, + texD3D, dxgiHandle) ); + return Move(ret); +} + +SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, GLuint rbGL, + DXInterop2Device* interop, + HANDLE lockHandle, + ID3D11Texture2D* texD3D, + HANDLE dxgiHandle) + : SharedSurface(SharedSurfaceType::DXGLInterop2, + AttachmentType::GLRenderbuffer, + gl, + size, + hasAlpha, + true) + , mProdRB(rbGL) + , mInterop(interop) + , mLockHandle(lockHandle) + , mTexD3D(texD3D) + , mDXGIHandle(dxgiHandle) + , mNeedsFinish(gfxPrefs::WebGLDXGLNeedsFinish()) + , mLockedForGL(false) +{ } + +SharedSurface_D3D11Interop::~SharedSurface_D3D11Interop() +{ + MOZ_ASSERT(!IsProducerAcquired()); + + if (!mGL || !mGL->MakeCurrent()) + return; + + if (!mInterop->UnregisterObject(mLockHandle)) { + NS_WARNING("Failed to release mLockHandle, possibly leaking it."); + } + + mGL->fDeleteRenderbuffers(1, &mProdRB); +} + +void +SharedSurface_D3D11Interop::ProducerAcquireImpl() +{ + MOZ_ASSERT(!mLockedForGL); + + // Now we have the mutex, we can lock for GL. + MOZ_ALWAYS_TRUE( mInterop->LockObject(mLockHandle) ); + + mLockedForGL = true; +} + +void +SharedSurface_D3D11Interop::ProducerReleaseImpl() +{ + MOZ_ASSERT(mLockedForGL); + + if (mNeedsFinish) { + mGL->fFinish(); + } else { + // We probably don't even need this. + mGL->fFlush(); + } + MOZ_ALWAYS_TRUE( mInterop->UnlockObject(mLockHandle) ); + + mLockedForGL = false; +} + +bool +SharedSurface_D3D11Interop::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + const auto format = (mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8 + : gfx::SurfaceFormat::B8G8R8X8); + *out_descriptor = layers::SurfaceDescriptorD3D10(WindowsHandle(mDXGIHandle), format, + mSize); + return true; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// Factory + +/*static*/ UniquePtr<SurfaceFactory_D3D11Interop> +SurfaceFactory_D3D11Interop::Create(GLContext* gl, const SurfaceCaps& caps, + layers::LayersIPCChannel* allocator, + const layers::TextureFlags& flags) +{ + WGLLibrary* wgl = &sWGLLib; + if (!wgl || !wgl->HasDXInterop2()) + return nullptr; + + const RefPtr<DXInterop2Device> interop = DXInterop2Device::Open(wgl, gl); + if (!interop) { + NS_WARNING("Failed to open D3D device for use by WGL."); + return nullptr; + } + + typedef SurfaceFactory_D3D11Interop ptrT; + UniquePtr<ptrT> ret(new ptrT(gl, caps, allocator, flags, interop)); + return Move(ret); +} + +SurfaceFactory_D3D11Interop::SurfaceFactory_D3D11Interop(GLContext* gl, + const SurfaceCaps& caps, + layers::LayersIPCChannel* allocator, + const layers::TextureFlags& flags, + DXInterop2Device* interop) + : SurfaceFactory(SharedSurfaceType::DXGLInterop2, gl, caps, allocator, flags) + , mInterop(interop) +{ } + +SurfaceFactory_D3D11Interop::~SurfaceFactory_D3D11Interop() +{ } + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h new file mode 100644 index 0000000000..0f5bd35cf5 --- /dev/null +++ b/gfx/gl/SharedSurfaceD3D11Interop.h @@ -0,0 +1,100 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 <windows.h> +#include "SharedSurface.h" + +namespace mozilla { +namespace gl { + +class DXInterop2Device; +class GLContext; +class WGLLibrary; + +class SharedSurface_D3D11Interop + : public SharedSurface +{ +public: + const GLuint mProdRB; + const RefPtr<DXInterop2Device> mInterop; + const HANDLE mLockHandle; + const RefPtr<ID3D11Texture2D> mTexD3D; + const HANDLE mDXGIHandle; + const bool mNeedsFinish; + +protected: + bool mLockedForGL; + +public: + static UniquePtr<SharedSurface_D3D11Interop> Create(DXInterop2Device* interop, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_D3D11Interop* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::DXGLInterop2); + return (SharedSurface_D3D11Interop*)surf; + } + +protected: + SharedSurface_D3D11Interop(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + GLuint renderbufferGL, + DXInterop2Device* interop, + HANDLE lockHandle, + ID3D11Texture2D* texD3D, + HANDLE dxgiHandle); + +public: + virtual ~SharedSurface_D3D11Interop() override; + + virtual void LockProdImpl() override { } + virtual void UnlockProdImpl() override { } + + virtual void ProducerAcquireImpl() override; + virtual void ProducerReleaseImpl() override; + + virtual GLuint ProdRenderbuffer() override { + return mProdRB; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; +}; + +class SurfaceFactory_D3D11Interop + : public SurfaceFactory +{ +public: + const RefPtr<DXInterop2Device> mInterop; + + static UniquePtr<SurfaceFactory_D3D11Interop> Create(GLContext* gl, + const SurfaceCaps& caps, + layers::LayersIPCChannel* allocator, + const layers::TextureFlags& flags); + +protected: + SurfaceFactory_D3D11Interop(GLContext* gl, const SurfaceCaps& caps, + layers::LayersIPCChannel* allocator, + const layers::TextureFlags& flags, + DXInterop2Device* interop); + +public: + virtual ~SurfaceFactory_D3D11Interop() override; + +protected: + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_D3D11Interop::Create(mInterop, mGL, size, hasAlpha); + } +}; + +} /* namespace gl */ +} /* namespace mozilla */ + +#endif /* SHARED_SURFACE_D3D11_INTEROP_H_ */ diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp new file mode 100644 index 0000000000..5538138e45 --- /dev/null +++ b/gfx/gl/SharedSurfaceEGL.cpp @@ -0,0 +1,191 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "GLLibraryEGL.h" +#include "GLReadTexImageHelper.h" +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc +#include "SharedSurface.h" +#include "TextureGarbageBin.h" + +namespace mozilla { +namespace gl { + +/*static*/ UniquePtr<SharedSurface_EGLImage> +SharedSurface_EGLImage::Create(GLContext* prodGL, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha, + EGLContext context) +{ + GLLibraryEGL* egl = &sEGLLibrary; + MOZ_ASSERT(egl); + MOZ_ASSERT(context); + + UniquePtr<SharedSurface_EGLImage> ret; + + if (!HasExtensions(egl, prodGL)) { + return Move(ret); + } + + MOZ_ALWAYS_TRUE(prodGL->MakeCurrent()); + GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size); + if (!prodTex) { + return Move(ret); + } + + EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(uintptr_t(prodTex)); + EGLImage image = egl->fCreateImage(egl->Display(), context, + LOCAL_EGL_GL_TEXTURE_2D, buffer, + nullptr); + if (!image) { + prodGL->fDeleteTextures(1, &prodTex); + return Move(ret); + } + + ret.reset( new SharedSurface_EGLImage(prodGL, egl, size, hasAlpha, + formats, prodTex, image) ); + return Move(ret); +} + +bool +SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl) +{ + return egl->HasKHRImageBase() && + egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) && + (gl->IsExtensionSupported(GLContext::OES_EGL_image_external) || + gl->IsExtensionSupported(GLContext::OES_EGL_image)); +} + +SharedSurface_EGLImage::SharedSurface_EGLImage(GLContext* gl, + GLLibraryEGL* egl, + const gfx::IntSize& size, + bool hasAlpha, + const GLFormats& formats, + GLuint prodTex, + EGLImage image) + : SharedSurface(SharedSurfaceType::EGLImageShare, + AttachmentType::GLTexture, + gl, + size, + hasAlpha, + false) // Can't recycle, as mSync changes never update TextureHost. + , mMutex("SharedSurface_EGLImage mutex") + , mEGL(egl) + , mFormats(formats) + , mProdTex(prodTex) + , mImage(image) + , mSync(0) +{} + +SharedSurface_EGLImage::~SharedSurface_EGLImage() +{ + mEGL->fDestroyImage(Display(), 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. + mEGL->fDestroySync(Display(), mSync); + mSync = 0; + } + + if (!mGL || !mGL->MakeCurrent()) + return; + + mGL->fDeleteTextures(1, &mProdTex); + mProdTex = 0; +} + +layers::TextureFlags +SharedSurface_EGLImage::GetTextureFlags() const +{ + return layers::TextureFlags::DEALLOCATE_CLIENT; +} + +void +SharedSurface_EGLImage::ProducerReleaseImpl() +{ + MutexAutoLock lock(mMutex); + mGL->MakeCurrent(); + + if (mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) && + mGL->IsExtensionSupported(GLContext::OES_EGL_sync)) + { + if (mSync) { + MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice."); + MOZ_ALWAYS_TRUE( mEGL->fDestroySync(Display(), mSync) ); + mSync = 0; + } + + mSync = mEGL->fCreateSync(Display(), + LOCAL_EGL_SYNC_FENCE, + nullptr); + if (mSync) { + mGL->fFlush(); + return; + } + } + + MOZ_ASSERT(!mSync); + mGL->fFinish(); +} + +void +SharedSurface_EGLImage::ProducerReadAcquireImpl() +{ + // Wait on the fence, because presumably we're going to want to read this surface + if (mSync) { + mEGL->fClientWaitSync(Display(), mSync, 0, LOCAL_EGL_FOREVER); + } +} + +EGLDisplay +SharedSurface_EGLImage::Display() const +{ + return mEGL->Display(); +} + +bool +SharedSurface_EGLImage::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + *out_descriptor = layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync, + mSize, mHasAlpha); + return true; +} + +bool +SharedSurface_EGLImage::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) +{ + MOZ_ASSERT(out_surface); + MOZ_ASSERT(NS_IsMainThread()); + return sEGLLibrary.ReadbackEGLImage(mImage, out_surface); +} + +//////////////////////////////////////////////////////////////////////// + +/*static*/ UniquePtr<SurfaceFactory_EGLImage> +SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) +{ + EGLContext context = GLContextEGL::Cast(prodGL)->mContext; + + typedef SurfaceFactory_EGLImage ptrT; + UniquePtr<ptrT> ret; + + GLLibraryEGL* egl = &sEGLLibrary; + if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) { + ret.reset( new ptrT(prodGL, caps, allocator, flags, context) ); + } + + return Move(ret); +} + +} // namespace gl + +} /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceEGL.h b/gfx/gl/SharedSurfaceEGL.h new file mode 100644 index 0000000000..98d0850058 --- /dev/null +++ b/gfx/gl/SharedSurfaceEGL.h @@ -0,0 +1,118 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "SharedSurface.h" + +namespace mozilla { +namespace gl { + +class GLContext; +class GLLibraryEGL; +class TextureGarbageBin; + +class SharedSurface_EGLImage + : public SharedSurface +{ +public: + static UniquePtr<SharedSurface_EGLImage> Create(GLContext* prodGL, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha, + EGLContext context); + + static SharedSurface_EGLImage* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::EGLImageShare); + + return (SharedSurface_EGLImage*)surf; + } + + static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl); + +protected: + mutable Mutex mMutex; + GLLibraryEGL* const mEGL; + const GLFormats mFormats; + GLuint mProdTex; +public: + const EGLImage mImage; +protected: + EGLSync mSync; + + SharedSurface_EGLImage(GLContext* gl, + GLLibraryEGL* egl, + const gfx::IntSize& size, + bool hasAlpha, + const GLFormats& formats, + GLuint prodTex, + EGLImage image); + + EGLDisplay Display() const; + void UpdateProdTexture(const MutexAutoLock& curAutoLock); + +public: + virtual ~SharedSurface_EGLImage(); + + virtual layers::TextureFlags GetTextureFlags() const override; + + virtual void LockProdImpl() override {} + virtual void UnlockProdImpl() override {} + + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; + + virtual void ProducerReadAcquireImpl() override; + virtual void ProducerReadReleaseImpl() override {}; + + virtual GLuint ProdTexture() override { + return mProdTex; + } + + // Implementation-specific functions below: + // Returns texture and target + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override; +}; + + + +class SurfaceFactory_EGLImage + : public SurfaceFactory +{ +public: + // Fallible: + static UniquePtr<SurfaceFactory_EGLImage> Create(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); + +protected: + const EGLContext mContext; + + SurfaceFactory_EGLImage(GLContext* prodGL, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags, + EGLContext context) + : SurfaceFactory(SharedSurfaceType::EGLImageShare, prodGL, caps, allocator, flags) + , mContext(context) + { } + +public: + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_EGLImage::Create(mGL, mFormats, size, hasAlpha, mContext); + } +}; + +} // 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..6fba1b4ebf --- /dev/null +++ b/gfx/gl/SharedSurfaceGL.cpp @@ -0,0 +1,190 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "ScopedGLHelpers.h" + +namespace mozilla { +namespace gl { + +using gfx::IntSize; +using gfx::SurfaceFormat; + +/*static*/ UniquePtr<SharedSurface_Basic> +SharedSurface_Basic::Create(GLContext* gl, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + UniquePtr<SharedSurface_Basic> ret; + gl->MakeCurrent(); + + GLContext::LocalErrorScope localError(*gl); + GLuint tex = CreateTextureForOffscreen(gl, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + gl->fDeleteTextures(1, &tex); + return Move(ret); + } + + bool ownsTex = true; + ret.reset( new SharedSurface_Basic(gl, size, hasAlpha, tex, ownsTex) ); + return Move(ret); +} + + +/*static*/ UniquePtr<SharedSurface_Basic> +SharedSurface_Basic::Wrap(GLContext* gl, + const IntSize& size, + bool hasAlpha, + GLuint tex) +{ + bool ownsTex = false; + UniquePtr<SharedSurface_Basic> ret( new SharedSurface_Basic(gl, size, hasAlpha, tex, + ownsTex) ); + return Move(ret); +} + +SharedSurface_Basic::SharedSurface_Basic(GLContext* gl, + const IntSize& size, + bool hasAlpha, + GLuint tex, + bool ownsTex) + : SharedSurface(SharedSurfaceType::Basic, + AttachmentType::GLTexture, + gl, + size, + hasAlpha, + true) + , mTex(tex) + , mOwnsTex(ownsTex) + , mFB(0) +{ + mGL->MakeCurrent(); + mGL->fGenFramebuffers(1, &mFB); + + ScopedBindFramebuffer autoFB(mGL, mFB); + mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, + LOCAL_GL_COLOR_ATTACHMENT0, + LOCAL_GL_TEXTURE_2D, + mTex, + 0); + + DebugOnly<GLenum> status = mGL->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); + MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE); +} + +SharedSurface_Basic::~SharedSurface_Basic() +{ + if (!mGL || !mGL->MakeCurrent()) + return; + + if (mFB) + mGL->fDeleteFramebuffers(1, &mFB); + + if (mOwnsTex) + mGL->fDeleteTextures(1, &mTex); +} + + +//////////////////////////////////////////////////////////////////////// + +SurfaceFactory_Basic::SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::Basic, gl, caps, nullptr, flags) +{ } + + +//////////////////////////////////////////////////////////////////////// +// SharedSurface_GLTexture + +/*static*/ UniquePtr<SharedSurface_GLTexture> +SharedSurface_GLTexture::Create(GLContext* prodGL, + const GLFormats& formats, + const IntSize& size, + bool hasAlpha) +{ + MOZ_ASSERT(prodGL); + + prodGL->MakeCurrent(); + + UniquePtr<SharedSurface_GLTexture> ret; + GLContext::LocalErrorScope localError(*prodGL); + + GLuint tex = CreateTextureForOffscreen(prodGL, formats, size); + + GLenum err = localError.GetError(); + MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY); + if (err) { + prodGL->fDeleteTextures(1, &tex); + return Move(ret); + } + + ret.reset(new SharedSurface_GLTexture(prodGL, size, + hasAlpha, tex)); + return Move(ret); +} + +SharedSurface_GLTexture::~SharedSurface_GLTexture() +{ + if (!mGL->MakeCurrent()) + return; + + if (mTex) { + mGL->fDeleteTextures(1, &mTex); + } + + if (mSync) { + mGL->fDeleteSync(mSync); + } +} + +void +SharedSurface_GLTexture::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + + if (mGL->IsSupported(GLFeature::sync)) { + if (mSync) { + mGL->fDeleteSync(mSync); + mSync = 0; + } + + mSync = mGL->fFenceSync(LOCAL_GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + if (mSync) { + mGL->fFlush(); + return; + } + } + MOZ_ASSERT(!mSync); + + mGL->fFinish(); +} + +bool +SharedSurface_GLTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + *out_descriptor = layers::SurfaceDescriptorSharedGLTexture(ProdTexture(), + ProdTextureTarget(), + (uintptr_t)mSync, + mSize, + mHasAlpha); + + // Transfer ownership of the fence to the host + mSync = nullptr; + return true; +} + + +} // namespace gl + +} /* namespace mozilla */ diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h new file mode 100644 index 0000000000..7574452710 --- /dev/null +++ b/gfx/gl/SharedSurfaceGL.h @@ -0,0 +1,167 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "ScopedGLHelpers.h" +#include "SharedSurface.h" +#include "SurfaceTypes.h" +#include "GLContextTypes.h" +#include "gfxTypes.h" +#include "mozilla/Mutex.h" + +#include <queue> + +namespace mozilla { + namespace gl { + class GLContext; + } // namespace gl + namespace gfx { + class DataSourceSurface; + } // namespace gfx +} // namespace mozilla + +namespace mozilla { +namespace gl { + +// For readback and bootstrapping: +class SharedSurface_Basic + : public SharedSurface +{ +public: + static UniquePtr<SharedSurface_Basic> Create(GLContext* gl, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha); + + static UniquePtr<SharedSurface_Basic> Wrap(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + GLuint tex); + + static SharedSurface_Basic* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::Basic); + + return (SharedSurface_Basic*)surf; + } + +protected: + const GLuint mTex; + const bool mOwnsTex; + GLuint mFB; + + SharedSurface_Basic(GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha, + GLuint tex, + bool ownsTex); + +public: + virtual ~SharedSurface_Basic(); + + virtual void LockProdImpl() override {} + virtual void UnlockProdImpl() override {} + + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override {} + + virtual GLuint ProdTexture() override { + return mTex; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override { + MOZ_CRASH("GFX: ToSurfaceDescriptor"); + return false; + } +}; + +class SurfaceFactory_Basic + : public SurfaceFactory +{ +public: + SurfaceFactory_Basic(GLContext* gl, const SurfaceCaps& caps, + const layers::TextureFlags& flags); + + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_Basic::Create(mGL, mFormats, size, hasAlpha); + } +}; + + +// Using shared GL textures: +class SharedSurface_GLTexture + : public SharedSurface +{ +public: + static UniquePtr<SharedSurface_GLTexture> Create(GLContext* prodGL, + const GLFormats& formats, + const gfx::IntSize& size, + bool hasAlpha); + + static SharedSurface_GLTexture* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::SharedGLTexture); + + return (SharedSurface_GLTexture*)surf; + } + +protected: + const GLuint mTex; + GLsync mSync; + + SharedSurface_GLTexture(GLContext* prodGL, + const gfx::IntSize& size, + bool hasAlpha, + GLuint tex) + : SharedSurface(SharedSurfaceType::SharedGLTexture, + AttachmentType::GLTexture, + prodGL, + size, + hasAlpha, true) + , mTex(tex) + , mSync(0) + { + } + +public: + virtual ~SharedSurface_GLTexture(); + + virtual void LockProdImpl() override {} + virtual void UnlockProdImpl() override {} + + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; + + virtual GLuint ProdTexture() override { + return mTex; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; +}; + +class SurfaceFactory_GLTexture + : public SurfaceFactory +{ +public: + SurfaceFactory_GLTexture(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::SharedGLTexture, prodGL, caps, allocator, flags) + { + } + + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override { + bool hasAlpha = mReadCaps.alpha; + return SharedSurface_GLTexture::Create(mGL, mFormats, size, hasAlpha); + } +}; + +} // namespace gl + +} /* namespace mozilla */ + +#endif /* SHARED_SURFACE_GL_H_ */ diff --git a/gfx/gl/SharedSurfaceGLX.cpp b/gfx/gl/SharedSurfaceGLX.cpp new file mode 100644 index 0000000000..69bee24bad --- /dev/null +++ b/gfx/gl/SharedSurfaceGLX.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "SharedSurfaceGLX.h" +#include "gfxXlibSurface.h" +#include "GLXLibrary.h" +#include "GLContextProvider.h" +#include "GLContextGLX.h" +#include "GLScreenBuffer.h" +#include "mozilla/gfx/SourceSurfaceCairo.h" +#include "mozilla/layers/LayersSurfaces.h" +#include "mozilla/layers/ShadowLayerUtilsX11.h" +#include "mozilla/layers/ISurfaceAllocator.h" +#include "mozilla/layers/TextureForwarder.h" +#include "mozilla/X11Util.h" + +namespace mozilla { +namespace gl { + +/* static */ +UniquePtr<SharedSurface_GLXDrawable> +SharedSurface_GLXDrawable::Create(GLContext* prodGL, + const SurfaceCaps& caps, + const gfx::IntSize& size, + bool deallocateClient, + bool inSameProcess) +{ + UniquePtr<SharedSurface_GLXDrawable> ret; + Display* display = DefaultXDisplay(); + Screen* screen = XDefaultScreenOfDisplay(display); + Visual* visual = gfxXlibSurface::FindVisual(screen, gfx::SurfaceFormat::A8R8G8B8_UINT32); + + RefPtr<gfxXlibSurface> surf = gfxXlibSurface::Create(screen, visual, size); + if (!deallocateClient) + surf->ReleasePixmap(); + + ret.reset(new SharedSurface_GLXDrawable(prodGL, size, inSameProcess, surf)); + return Move(ret); +} + + +SharedSurface_GLXDrawable::SharedSurface_GLXDrawable(GLContext* gl, + const gfx::IntSize& size, + bool inSameProcess, + const RefPtr<gfxXlibSurface>& xlibSurface) + : SharedSurface(SharedSurfaceType::GLXDrawable, + AttachmentType::Screen, + gl, + size, + true, + true) + , mXlibSurface(xlibSurface) + , mInSameProcess(inSameProcess) +{} + +void +SharedSurface_GLXDrawable::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + mGL->fFlush(); +} + +void +SharedSurface_GLXDrawable::LockProdImpl() +{ + mGL->Screen()->SetReadBuffer(LOCAL_GL_FRONT); + GLContextGLX::Cast(mGL)->OverrideDrawable(mXlibSurface->GetGLXPixmap()); +} + +void +SharedSurface_GLXDrawable::UnlockProdImpl() +{ + GLContextGLX::Cast(mGL)->RestoreDrawable(); +} + +bool +SharedSurface_GLXDrawable::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + if (!mXlibSurface) + return false; + + *out_descriptor = layers::SurfaceDescriptorX11(mXlibSurface, mInSameProcess); + return true; +} + +bool +SharedSurface_GLXDrawable::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) +{ + MOZ_ASSERT(out_surface); + RefPtr<gfx::DataSourceSurface> dataSurf = + new gfx::DataSourceSurfaceCairo(mXlibSurface->CairoSurface()); + + gfx::DataSourceSurface::ScopedMap mapSrc(dataSurf, gfx::DataSourceSurface::READ); + if (!mapSrc.IsMapped()) { + return false; + } + + gfx::DataSourceSurface::ScopedMap mapDest(out_surface, gfx::DataSourceSurface::WRITE); + if (!mapDest.IsMapped()) { + return false; + } + + if (mapDest.GetStride() == mapSrc.GetStride()) { + memcpy(mapDest.GetData(), + mapSrc.GetData(), + out_surface->GetSize().height * mapDest.GetStride()); + } else { + for (int32_t i = 0; i < dataSurf->GetSize().height; i++) { + memcpy(mapDest.GetData() + i * mapDest.GetStride(), + mapSrc.GetData() + i * mapSrc.GetStride(), + std::min(mapSrc.GetStride(), mapDest.GetStride())); + } + } + + return true; +} + +/* static */ +UniquePtr<SurfaceFactory_GLXDrawable> +SurfaceFactory_GLXDrawable::Create(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) +{ + MOZ_ASSERT(caps.alpha, "GLX surfaces require an alpha channel!"); + + typedef SurfaceFactory_GLXDrawable ptrT; + UniquePtr<ptrT> ret(new ptrT(prodGL, caps, allocator, + flags & ~layers::TextureFlags::ORIGIN_BOTTOM_LEFT)); + return Move(ret); +} + +UniquePtr<SharedSurface> +SurfaceFactory_GLXDrawable::CreateShared(const gfx::IntSize& size) +{ + bool deallocateClient = !!(mFlags & layers::TextureFlags::DEALLOCATE_CLIENT); + return SharedSurface_GLXDrawable::Create(mGL, mCaps, size, deallocateClient, + mAllocator->IsSameProcess()); +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/SharedSurfaceGLX.h b/gfx/gl/SharedSurfaceGLX.h new file mode 100644 index 0000000000..19a0338b26 --- /dev/null +++ b/gfx/gl/SharedSurfaceGLX.h @@ -0,0 +1,68 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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_GLX_H_ +#define SHARED_SURFACE_GLX_H_ + +#include "SharedSurface.h" +#include "mozilla/RefPtr.h" + +class gfxXlibSurface; + +namespace mozilla { +namespace gl { + +class SharedSurface_GLXDrawable + : public SharedSurface +{ +public: + static UniquePtr<SharedSurface_GLXDrawable> Create(GLContext* prodGL, + const SurfaceCaps& caps, + const gfx::IntSize& size, + bool deallocateClient, + bool inSameProcess); + + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; + + virtual void LockProdImpl() override; + virtual void UnlockProdImpl() override; + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override; +private: + SharedSurface_GLXDrawable(GLContext* gl, + const gfx::IntSize& size, + bool inSameProcess, + const RefPtr<gfxXlibSurface>& xlibSurface); + + RefPtr<gfxXlibSurface> mXlibSurface; + bool mInSameProcess; +}; + +class SurfaceFactory_GLXDrawable + : public SurfaceFactory +{ +public: + static UniquePtr<SurfaceFactory_GLXDrawable> Create(GLContext* prodGL, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); + + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override; + +private: + SurfaceFactory_GLXDrawable(GLContext* prodGL, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) + : SurfaceFactory(SharedSurfaceType::GLXDrawable, prodGL, caps, allocator, flags) + { } +}; + +} // namespace gl +} // namespace mozilla + +#endif // SHARED_SURFACE_GLX_H_ diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp new file mode 100644 index 0000000000..50262d6cce --- /dev/null +++ b/gfx/gl/SharedSurfaceIO.cpp @@ -0,0 +1,248 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "mozilla/DebugOnly.h" +#include "mozilla/gfx/MacIOSurface.h" +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc +#include "ScopedGLHelpers.h" + +namespace mozilla { +namespace gl { + +/*static*/ UniquePtr<SharedSurface_IOSurface> +SharedSurface_IOSurface::Create(const RefPtr<MacIOSurface>& ioSurf, + GLContext* gl, + bool hasAlpha) +{ + MOZ_ASSERT(ioSurf); + MOZ_ASSERT(gl); + + auto size = gfx::IntSize::Truncate(ioSurf->GetWidth(), ioSurf->GetHeight()); + + typedef SharedSurface_IOSurface ptrT; + UniquePtr<ptrT> ret( new ptrT(ioSurf, gl, size, hasAlpha) ); + return Move(ret); +} + +void +SharedSurface_IOSurface::ProducerReleaseImpl() +{ + mGL->MakeCurrent(); + mGL->fFlush(); +} + +bool +SharedSurface_IOSurface::CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + /* Bug 896693 - OpenGL framebuffers that are backed by IOSurface on OSX expose a bug + * in glCopyTexImage2D --- internalformats GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA + * return the wrong results. To work around, copy framebuffer to a temporary texture + * using GL_RGBA (which works), attach as read framebuffer and glCopyTexImage2D + * instead. + */ + + // https://www.opengl.org/sdk/docs/man3/xhtml/glCopyTexImage2D.xml says that width or + // height set to 0 results in a NULL texture. Lets not do any work and punt to + // original glCopyTexImage2D, since the FBO below will fail when trying to attach a + // texture of 0 width or height. + if (width == 0 || height == 0) + return false; + + switch (internalformat) { + case LOCAL_GL_ALPHA: + case LOCAL_GL_LUMINANCE: + case LOCAL_GL_LUMINANCE_ALPHA: + break; + + default: + return false; + } + + MOZ_ASSERT(mGL->IsCurrent()); + + ScopedTexture destTex(mGL); + { + ScopedBindTexture bindTex(mGL, destTex.Texture()); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, + LOCAL_GL_NEAREST); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, + LOCAL_GL_NEAREST); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, + LOCAL_GL_CLAMP_TO_EDGE); + mGL->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, + LOCAL_GL_CLAMP_TO_EDGE); + mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, x, y, width, + height, 0); + } + + ScopedFramebufferForTexture tmpFB(mGL, destTex.Texture(), LOCAL_GL_TEXTURE_2D); + ScopedBindFramebuffer bindFB(mGL, tmpFB.FB()); + mGL->raw_fCopyTexImage2D(target, level, internalformat, x, y, width, height, border); + + return true; +} + +bool +SharedSurface_IOSurface::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid* pixels) +{ + // Calling glReadPixels when an IOSurface is bound to the current framebuffer + // can cause corruption in following glReadPixel calls (even if they aren't + // reading from an IOSurface). + // We workaround this by copying to a temporary texture, and doing the readback + // from that. + MOZ_ASSERT(mGL->IsCurrent()); + + ScopedTexture destTex(mGL); + { + ScopedFramebufferForTexture srcFB(mGL, ProdTexture(), ProdTextureTarget()); + + ScopedBindFramebuffer bindFB(mGL, srcFB.FB()); + ScopedBindTexture bindTex(mGL, destTex.Texture()); + mGL->raw_fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, + mHasAlpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB, + x, y, + width, height, 0); + } + + ScopedFramebufferForTexture destFB(mGL, destTex.Texture()); + + ScopedBindFramebuffer bindFB(mGL, destFB.FB()); + mGL->raw_fReadPixels(0, 0, width, height, format, type, pixels); + return true; +} + +static void +BackTextureWithIOSurf(GLContext* gl, GLuint tex, MacIOSurface* 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(cgl); +} + +SharedSurface_IOSurface::SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf, + GLContext* gl, + const gfx::IntSize& size, + bool hasAlpha) + : SharedSurface(SharedSurfaceType::IOSurface, + AttachmentType::GLTexture, + gl, + size, + hasAlpha, + true) + , mIOSurf(ioSurf) +{ + gl->MakeCurrent(); + mProdTex = 0; + gl->fGenTextures(1, &mProdTex); + BackTextureWithIOSurf(gl, mProdTex, mIOSurf); +} + +SharedSurface_IOSurface::~SharedSurface_IOSurface() +{ + if (!mGL || !mGL->MakeCurrent()) + return; + + mGL->fDeleteTextures(1, &mProdTex); +} + +bool +SharedSurface_IOSurface::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) +{ + bool isOpaque = !mHasAlpha; + *out_descriptor = layers::SurfaceDescriptorMacIOSurface(mIOSurf->GetIOSurfaceID(), + mIOSurf->GetContentsScaleFactor(), + isOpaque); + return true; +} + +bool +SharedSurface_IOSurface::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) +{ + MOZ_ASSERT(out_surface); + mIOSurf->Lock(); + size_t bytesPerRow = mIOSurf->GetBytesPerRow(); + size_t ioWidth = mIOSurf->GetDevicePixelWidth(); + size_t ioHeight = mIOSurf->GetDevicePixelHeight(); + + const unsigned char* ioData = (unsigned char*)mIOSurf->GetBaseAddress(); + gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE); + if (!map.IsMapped()) { + mIOSurf->Unlock(); + return false; + } + + for (size_t i = 0; i < ioHeight; i++) { + memcpy(map.GetData() + i * map.GetStride(), + ioData + i * bytesPerRow, ioWidth * 4); + } + + mIOSurf->Unlock(); + return true; +} + +//////////////////////////////////////////////////////////////////////// +// SurfaceFactory_IOSurface + +/*static*/ UniquePtr<SurfaceFactory_IOSurface> +SurfaceFactory_IOSurface::Create(GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags) +{ + auto maxDims = gfx::IntSize::Truncate(MacIOSurface::GetMaxWidth(), + MacIOSurface::GetMaxHeight()); + + typedef SurfaceFactory_IOSurface ptrT; + UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, maxDims) ); + return Move(ret); +} + +UniquePtr<SharedSurface> +SurfaceFactory_IOSurface::CreateShared(const gfx::IntSize& size) +{ + if (size.width > mMaxDims.width || + size.height > mMaxDims.height) + { + return nullptr; + } + + bool hasAlpha = mReadCaps.alpha; + RefPtr<MacIOSurface> ioSurf; + ioSurf = MacIOSurface::CreateIOSurface(size.width, size.height, 1.0, + hasAlpha); + + if (!ioSurf) { + NS_WARNING("Failed to create MacIOSurface."); + return nullptr; + } + + return SharedSurface_IOSurface::Create(ioSurf, mGL, hasAlpha); +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/SharedSurfaceIO.h b/gfx/gl/SharedSurfaceIO.h new file mode 100644 index 0000000000..16e0cbbb7f --- /dev/null +++ b/gfx/gl/SharedSurfaceIO.h @@ -0,0 +1,100 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 SharedSurface_IOSurface : public SharedSurface +{ +private: + const RefPtr<MacIOSurface> mIOSurf; + GLuint mProdTex; + +public: + static UniquePtr<SharedSurface_IOSurface> Create(const RefPtr<MacIOSurface>& ioSurf, + GLContext* gl, + bool hasAlpha); + +private: + SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf, + GLContext* gl, const gfx::IntSize& size, + bool hasAlpha); + +public: + ~SharedSurface_IOSurface(); + + virtual void LockProdImpl() override { } + virtual void UnlockProdImpl() override { } + + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; + + virtual bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) override; + virtual bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid* pixels) override; + + virtual GLuint ProdTexture() override { + return mProdTex; + } + + virtual GLenum ProdTextureTarget() const override { + return LOCAL_GL_TEXTURE_RECTANGLE_ARB; + } + + static SharedSurface_IOSurface* Cast(SharedSurface* surf) { + MOZ_ASSERT(surf->mType == SharedSurfaceType::IOSurface); + return static_cast<SharedSurface_IOSurface*>(surf); + } + + MacIOSurface* GetIOSurface() const { + return mIOSurf; + } + + virtual bool NeedsIndirectReads() const override { + return true; + } + + virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override; + + virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override; +}; + +class SurfaceFactory_IOSurface : public SurfaceFactory +{ +public: + // Infallible. + static UniquePtr<SurfaceFactory_IOSurface> Create(GLContext* gl, + const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags); +protected: + const gfx::IntSize mMaxDims; + + SurfaceFactory_IOSurface(GLContext* gl, const SurfaceCaps& caps, + const RefPtr<layers::LayersIPCChannel>& allocator, + const layers::TextureFlags& flags, + const gfx::IntSize& maxDims) + : SurfaceFactory(SharedSurfaceType::IOSurface, gl, caps, allocator, flags) + , mMaxDims(maxDims) + { } + + virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override; +}; + +} // namespace gl + +} /* namespace mozilla */ + +#endif /* SHARED_SURFACEIO_H_ */ diff --git a/gfx/gl/SkiaGLGlue.cpp b/gfx/gl/SkiaGLGlue.cpp new file mode 100755 index 0000000000..eb84934a66 --- /dev/null +++ b/gfx/gl/SkiaGLGlue.cpp @@ -0,0 +1,327 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "skia/include/gpu/GrContext.h" +#include "skia/include/gpu/gl/GrGLInterface.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/ThreadLocal.h" +#include "mozilla/DebugOnly.h" + +/* SkPostConfig.h includes windows.h, which includes windef.h + * which redefines min/max. We don't want that. */ +#ifdef _WIN32 +#undef min +#undef max +#endif + +#include "GLContext.h" +#include "SkiaGLGlue.h" + +using mozilla::gl::GLContext; +using mozilla::gl::GLFeature; +using mozilla::gl::SkiaGLGlue; +using mozilla::gfx::DrawTarget; + +template<typename R, typename... A> +static inline GrGLFunction<R (*)(A...)> +WrapGL(RefPtr<GLContext> aContext, R (GLContext::*aFunc)(A...)) +{ + return [aContext, aFunc] (A... args) -> R + { + aContext->MakeCurrent(); + return (aContext->*aFunc)(args...); + }; +} + +template<typename R, typename... A> +static inline GrGLFunction<R (*)(A...)> +WrapGL(RefPtr<GLContext> aContext, R (*aFunc)(GLContext*, A...)) +{ + return [aContext, aFunc] (A... args) -> R + { + aContext->MakeCurrent(); + return (*aFunc)(aContext, args...); + }; +} + +// Core GL functions required by Ganesh + +static const GLubyte* +glGetString_mozilla(GLContext* aContext, GrGLenum aName) +{ + // GLContext only exposes a OpenGL 2.0 style API, so we have to intercept a bunch + // of checks that Ganesh makes to determine which capabilities are present + // on the GL implementation and change them to match what GLContext actually exposes. + + if (aName == LOCAL_GL_VERSION) { + if (aContext->IsGLES()) { + return reinterpret_cast<const GLubyte*>("OpenGL ES 2.0"); + } else { + return reinterpret_cast<const GLubyte*>("2.0"); + } + } else if (aName == LOCAL_GL_EXTENSIONS) { + // Only expose the bare minimum extensions we want to support to ensure a functional Ganesh + // as GLContext only exposes certain extensions + static bool extensionsStringBuilt = false; + static char extensionsString[1024]; + + if (!extensionsStringBuilt) { + extensionsString[0] = '\0'; + + if (aContext->IsGLES()) { + // OES is only applicable to GLES2 + if (aContext->IsExtensionSupported(GLContext::OES_packed_depth_stencil)) { + strcat(extensionsString, "GL_OES_packed_depth_stencil "); + } + + if (aContext->IsExtensionSupported(GLContext::OES_rgb8_rgba8)) { + strcat(extensionsString, "GL_OES_rgb8_rgba8 "); + } + + if (aContext->IsExtensionSupported(GLContext::OES_texture_npot)) { + strcat(extensionsString, "GL_OES_texture_npot "); + } + + if (aContext->IsExtensionSupported(GLContext::OES_vertex_array_object)) { + strcat(extensionsString, "GL_OES_vertex_array_object "); + } + + if (aContext->IsSupported(GLFeature::standard_derivatives)) { + strcat(extensionsString, "GL_OES_standard_derivatives "); + } + } else { + if (aContext->IsSupported(GLFeature::framebuffer_object)) { + strcat(extensionsString, "GL_ARB_framebuffer_object "); + } else if (aContext->IsExtensionSupported(GLContext::EXT_framebuffer_object)) { + strcat(extensionsString, "GL_EXT_framebuffer_object "); + } + + if (aContext->IsSupported(GLFeature::texture_rg)) { + strcat(extensionsString, "GL_ARB_texture_rg "); + } + } + + if (aContext->IsExtensionSupported(GLContext::EXT_texture_format_BGRA8888)) { + strcat(extensionsString, "GL_EXT_texture_format_BGRA8888 "); + } + + if (aContext->IsExtensionSupported(GLContext::EXT_packed_depth_stencil)) { + strcat(extensionsString, "GL_EXT_packed_depth_stencil "); + } + + if (aContext->IsExtensionSupported(GLContext::EXT_bgra)) { + strcat(extensionsString, "GL_EXT_bgra "); + } + + if (aContext->IsExtensionSupported(GLContext::EXT_read_format_bgra)) { + strcat(extensionsString, "GL_EXT_read_format_bgra "); + } + + extensionsStringBuilt = true; +#ifdef DEBUG + printf_stderr("Exported SkiaGL extensions: %s\n", extensionsString); +#endif + } + + return reinterpret_cast<const GLubyte*>(extensionsString); + + } else if (aName == LOCAL_GL_SHADING_LANGUAGE_VERSION) { + if (aContext->IsGLES()) { + return reinterpret_cast<const GLubyte*>("OpenGL ES GLSL ES 1.0"); + } else { + return reinterpret_cast<const GLubyte*>("1.10"); + } + } + + return aContext->fGetString(aName); +} + +static GrGLInterface* CreateGrGLInterfaceFromGLContext(GLContext* context) +{ + GrGLInterface* i = new GrGLInterface(); + + context->MakeCurrent(); + + // We support both desktop GL and GLES2 + if (context->IsGLES()) { + i->fStandard = kGLES_GrGLStandard; + } else { + i->fStandard = kGL_GrGLStandard; + } + + GrGLFunction<GrGLGetStringProc> getString = WrapGL(context, &glGetString_mozilla); + GrGLFunction<GrGLGetIntegervProc> getIntegerv = WrapGL(context, &GLContext::fGetIntegerv); + + GrGLExtensions extensions; + if (!extensions.init(i->fStandard, getString, nullptr, getIntegerv)) { + delete i; + return nullptr; + } + + i->fExtensions.swap(&extensions); + + // Core GL functions required by Ganesh + i->fFunctions.fActiveTexture = WrapGL(context, &GLContext::fActiveTexture); + i->fFunctions.fAttachShader = WrapGL(context, &GLContext::fAttachShader); + i->fFunctions.fBindAttribLocation = WrapGL(context, &GLContext::fBindAttribLocation); + i->fFunctions.fBindBuffer = WrapGL(context, &GLContext::fBindBuffer); + i->fFunctions.fBindFramebuffer = WrapGL(context, &GLContext::fBindFramebuffer); + i->fFunctions.fBindRenderbuffer = WrapGL(context, &GLContext::fBindRenderbuffer); + i->fFunctions.fBindTexture = WrapGL(context, &GLContext::fBindTexture); + i->fFunctions.fBlendFunc = WrapGL(context, &GLContext::fBlendFunc); + i->fFunctions.fBlendColor = WrapGL(context, &GLContext::fBlendColor); + i->fFunctions.fBlendEquation = WrapGL(context, &GLContext::fBlendEquation); + i->fFunctions.fBufferData = WrapGL(context, &GLContext::fBufferData); + i->fFunctions.fBufferSubData = WrapGL(context, &GLContext::fBufferSubData); + i->fFunctions.fCheckFramebufferStatus = WrapGL(context, &GLContext::fCheckFramebufferStatus); + i->fFunctions.fClear = WrapGL(context, &GLContext::fClear); + i->fFunctions.fClearColor = WrapGL(context, &GLContext::fClearColor); + i->fFunctions.fClearStencil = WrapGL(context, &GLContext::fClearStencil); + i->fFunctions.fColorMask = WrapGL(context, &GLContext::fColorMask); + i->fFunctions.fCompileShader = WrapGL(context, &GLContext::fCompileShader); + i->fFunctions.fCopyTexSubImage2D = WrapGL(context, &GLContext::fCopyTexSubImage2D); + i->fFunctions.fCreateProgram = WrapGL(context, &GLContext::fCreateProgram); + i->fFunctions.fCreateShader = WrapGL(context, &GLContext::fCreateShader); + i->fFunctions.fCullFace = WrapGL(context, &GLContext::fCullFace); + i->fFunctions.fDeleteBuffers = WrapGL(context, &GLContext::fDeleteBuffers); + i->fFunctions.fDeleteFramebuffers = WrapGL(context, &GLContext::fDeleteFramebuffers); + i->fFunctions.fDeleteProgram = WrapGL(context, &GLContext::fDeleteProgram); + i->fFunctions.fDeleteRenderbuffers = WrapGL(context, &GLContext::fDeleteRenderbuffers); + i->fFunctions.fDeleteShader = WrapGL(context, &GLContext::fDeleteShader); + i->fFunctions.fDeleteTextures = WrapGL(context, &GLContext::fDeleteTextures); + i->fFunctions.fDepthMask = WrapGL(context, &GLContext::fDepthMask); + i->fFunctions.fDisable = WrapGL(context, &GLContext::fDisable); + i->fFunctions.fDisableVertexAttribArray = WrapGL(context, &GLContext::fDisableVertexAttribArray); + i->fFunctions.fDrawArrays = WrapGL(context, &GLContext::fDrawArrays); + i->fFunctions.fDrawElements = WrapGL(context, &GLContext::fDrawElements); + i->fFunctions.fDrawRangeElements = WrapGL(context, &GLContext::fDrawRangeElements); + i->fFunctions.fEnable = WrapGL(context, &GLContext::fEnable); + i->fFunctions.fEnableVertexAttribArray = WrapGL(context, &GLContext::fEnableVertexAttribArray); + i->fFunctions.fFinish = WrapGL(context, &GLContext::fFinish); + i->fFunctions.fFlush = WrapGL(context, &GLContext::fFlush); + i->fFunctions.fFramebufferRenderbuffer = WrapGL(context, &GLContext::fFramebufferRenderbuffer); + i->fFunctions.fFramebufferTexture2D = WrapGL(context, &GLContext::fFramebufferTexture2D); + i->fFunctions.fFrontFace = WrapGL(context, &GLContext::fFrontFace); + i->fFunctions.fGenBuffers = WrapGL(context, &GLContext::fGenBuffers); + i->fFunctions.fGenFramebuffers = WrapGL(context, &GLContext::fGenFramebuffers); + i->fFunctions.fGenRenderbuffers = WrapGL(context, &GLContext::fGenRenderbuffers); + i->fFunctions.fGetFramebufferAttachmentParameteriv = WrapGL(context, &GLContext::fGetFramebufferAttachmentParameteriv); + i->fFunctions.fGenTextures = WrapGL(context, &GLContext::fGenTextures); + i->fFunctions.fGenerateMipmap = WrapGL(context, &GLContext::fGenerateMipmap); + i->fFunctions.fGetBufferParameteriv = WrapGL(context, &GLContext::fGetBufferParameteriv); + i->fFunctions.fGetError = WrapGL(context, &GLContext::fGetError); + i->fFunctions.fGetIntegerv = getIntegerv; + i->fFunctions.fGetProgramInfoLog = WrapGL(context, &GLContext::fGetProgramInfoLog); + i->fFunctions.fGetProgramiv = WrapGL(context, &GLContext::fGetProgramiv); + i->fFunctions.fGetRenderbufferParameteriv = WrapGL(context, &GLContext::fGetRenderbufferParameteriv); + i->fFunctions.fGetShaderInfoLog = WrapGL(context, &GLContext::fGetShaderInfoLog); + i->fFunctions.fGetShaderiv = WrapGL(context, &GLContext::fGetShaderiv); + i->fFunctions.fGetShaderPrecisionFormat = WrapGL(context, &GLContext::fGetShaderPrecisionFormat); + i->fFunctions.fGetString = getString; + i->fFunctions.fGetUniformLocation = WrapGL(context, &GLContext::fGetUniformLocation); + i->fFunctions.fLineWidth = WrapGL(context, &GLContext::fLineWidth); + i->fFunctions.fLinkProgram = WrapGL(context, &GLContext::fLinkProgram); + i->fFunctions.fPixelStorei = WrapGL(context, &GLContext::fPixelStorei); + i->fFunctions.fReadPixels = WrapGL(context, &GLContext::fReadPixels); + i->fFunctions.fRenderbufferStorage = WrapGL(context, &GLContext::fRenderbufferStorage); + i->fFunctions.fScissor = WrapGL(context, &GLContext::fScissor); + i->fFunctions.fShaderSource = WrapGL(context, &GLContext::fShaderSource); + i->fFunctions.fStencilFunc = WrapGL(context, &GLContext::fStencilFunc); + i->fFunctions.fStencilMask = WrapGL(context, &GLContext::fStencilMask); + i->fFunctions.fStencilOp = WrapGL(context, &GLContext::fStencilOp); + i->fFunctions.fTexImage2D = WrapGL(context, &GLContext::fTexImage2D); + i->fFunctions.fTexParameteri = WrapGL(context, &GLContext::fTexParameteri); + i->fFunctions.fTexParameteriv = WrapGL(context, &GLContext::fTexParameteriv); + i->fFunctions.fTexSubImage2D = WrapGL(context, &GLContext::fTexSubImage2D); + i->fFunctions.fUniform1f = WrapGL(context, &GLContext::fUniform1f); + i->fFunctions.fUniform1i = WrapGL(context, &GLContext::fUniform1i); + i->fFunctions.fUniform1fv = WrapGL(context, &GLContext::fUniform1fv); + i->fFunctions.fUniform1iv = WrapGL(context, &GLContext::fUniform1iv); + i->fFunctions.fUniform2f = WrapGL(context, &GLContext::fUniform2f); + i->fFunctions.fUniform2i = WrapGL(context, &GLContext::fUniform2i); + i->fFunctions.fUniform2fv = WrapGL(context, &GLContext::fUniform2fv); + i->fFunctions.fUniform2iv = WrapGL(context, &GLContext::fUniform2iv); + i->fFunctions.fUniform3f = WrapGL(context, &GLContext::fUniform3f); + i->fFunctions.fUniform3i = WrapGL(context, &GLContext::fUniform3i); + i->fFunctions.fUniform3fv = WrapGL(context, &GLContext::fUniform3fv); + i->fFunctions.fUniform3iv = WrapGL(context, &GLContext::fUniform3iv); + i->fFunctions.fUniform4f = WrapGL(context, &GLContext::fUniform4f); + i->fFunctions.fUniform4i = WrapGL(context, &GLContext::fUniform4i); + i->fFunctions.fUniform4fv = WrapGL(context, &GLContext::fUniform4fv); + i->fFunctions.fUniform4iv = WrapGL(context, &GLContext::fUniform4iv); + i->fFunctions.fUniformMatrix2fv = WrapGL(context, &GLContext::fUniformMatrix2fv); + i->fFunctions.fUniformMatrix3fv = WrapGL(context, &GLContext::fUniformMatrix3fv); + i->fFunctions.fUniformMatrix4fv = WrapGL(context, &GLContext::fUniformMatrix4fv); + i->fFunctions.fUseProgram = WrapGL(context, &GLContext::fUseProgram); + i->fFunctions.fVertexAttrib1f = WrapGL(context, &GLContext::fVertexAttrib1f); + i->fFunctions.fVertexAttrib2fv = WrapGL(context, &GLContext::fVertexAttrib2fv); + i->fFunctions.fVertexAttrib3fv = WrapGL(context, &GLContext::fVertexAttrib3fv); + i->fFunctions.fVertexAttrib4fv = WrapGL(context, &GLContext::fVertexAttrib4fv); + i->fFunctions.fVertexAttribPointer = WrapGL(context, &GLContext::fVertexAttribPointer); + i->fFunctions.fViewport = WrapGL(context, &GLContext::fViewport); + + // Required for either desktop OpenGL 2.0 or OpenGL ES 2.0 + i->fFunctions.fStencilFuncSeparate = WrapGL(context, &GLContext::fStencilFuncSeparate); + i->fFunctions.fStencilMaskSeparate = WrapGL(context, &GLContext::fStencilMaskSeparate); + i->fFunctions.fStencilOpSeparate = WrapGL(context, &GLContext::fStencilOpSeparate); + + // GLContext supports glMapBuffer + i->fFunctions.fMapBuffer = WrapGL(context, &GLContext::fMapBuffer); + i->fFunctions.fUnmapBuffer = WrapGL(context, &GLContext::fUnmapBuffer); + + // GLContext supports glRenderbufferStorageMultisample/glBlitFramebuffer + i->fFunctions.fRenderbufferStorageMultisample = WrapGL(context, &GLContext::fRenderbufferStorageMultisample); + i->fFunctions.fBlitFramebuffer = WrapGL(context, &GLContext::fBlitFramebuffer); + + // GLContext supports glCompressedTexImage2D + i->fFunctions.fCompressedTexImage2D = WrapGL(context, &GLContext::fCompressedTexImage2D); + + // GL_OES_vertex_array_object + i->fFunctions.fBindVertexArray = WrapGL(context, &GLContext::fBindVertexArray); + i->fFunctions.fDeleteVertexArrays = WrapGL(context, &GLContext::fDeleteVertexArrays); + i->fFunctions.fGenVertexArrays = WrapGL(context, &GLContext::fGenVertexArrays); + + // Desktop GL + i->fFunctions.fGetTexLevelParameteriv = WrapGL(context, &GLContext::fGetTexLevelParameteriv); + i->fFunctions.fDrawBuffer = WrapGL(context, &GLContext::fDrawBuffer); + i->fFunctions.fReadBuffer = WrapGL(context, &GLContext::fReadBuffer); + + // Desktop OpenGL > 1.5 + i->fFunctions.fGenQueries = WrapGL(context, &GLContext::fGenQueries); + i->fFunctions.fDeleteQueries = WrapGL(context, &GLContext::fDeleteQueries); + i->fFunctions.fBeginQuery = WrapGL(context, &GLContext::fBeginQuery); + i->fFunctions.fEndQuery = WrapGL(context, &GLContext::fEndQuery); + i->fFunctions.fGetQueryiv = WrapGL(context, &GLContext::fGetQueryiv); + i->fFunctions.fGetQueryObjectiv = WrapGL(context, &GLContext::fGetQueryObjectiv); + i->fFunctions.fGetQueryObjectuiv = WrapGL(context, &GLContext::fGetQueryObjectuiv); + + // Desktop OpenGL > 2.0 + i->fFunctions.fDrawBuffers = WrapGL(context, &GLContext::fDrawBuffers); + + return i; +} + +SkiaGLGlue::SkiaGLGlue(GLContext* context) + : mGLContext(context) +{ + mGrGLInterface.reset(CreateGrGLInterfaceFromGLContext(mGLContext)); + mGrContext.reset(GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)mGrGLInterface.get())); +} + +SkiaGLGlue::~SkiaGLGlue() +{ + /* + * These members have inter-dependencies, but do not keep each other alive, so + * destruction order is very important here: mGrContext uses mGrGLInterface, and + * through it, uses mGLContext + */ + mGrContext = nullptr; + if (mGrGLInterface) { + // Ensure that no references to the GLContext remain, even if the GrContext still lives. + mGrGLInterface->fFunctions = GrGLInterface::Functions(); + mGrGLInterface = nullptr; + } + mGLContext = nullptr; +} diff --git a/gfx/gl/SkiaGLGlue.h b/gfx/gl/SkiaGLGlue.h new file mode 100755 index 0000000000..4110c0c547 --- /dev/null +++ b/gfx/gl/SkiaGLGlue.h @@ -0,0 +1,64 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 SKIA_GL_GLUE_H_ +#define SKIA_GL_GLUE_H_ + +#ifdef USE_SKIA_GPU + +#include "skia/include/core/SkRefCnt.h" +#include "mozilla/RefPtr.h" + +struct GrGLInterface; +class GrContext; + +namespace mozilla { +namespace gl { + +class GLContext; + +class SkiaGLGlue : public GenericAtomicRefCounted +{ +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SkiaGLGlue) + explicit SkiaGLGlue(GLContext* context); + GLContext* GetGLContext() const { return mGLContext.get(); } + GrContext* GetGrContext() const { return mGrContext.get(); } + +protected: + virtual ~SkiaGLGlue(); + +private: + RefPtr<GLContext> mGLContext; + sk_sp<GrGLInterface> mGrGLInterface; + sk_sp<GrContext> mGrContext; +}; + +} // namespace gl +} // namespace mozilla + +#else // USE_SKIA_GPU + +class GrContext; + +namespace mozilla { +namespace gl { + +class GLContext; + +class SkiaGLGlue : public GenericAtomicRefCounted +{ +public: + SkiaGLGlue(GLContext* context); + GLContext* GetGLContext() const { return nullptr; } + GrContext* GetGrContext() const { return nullptr; } +}; + +} // namespace gl +} // namespace mozilla + +#endif // USE_SKIA_GPU + +#endif // SKIA_GL_GLUE_H_ diff --git a/gfx/gl/SurfaceTypes.cpp b/gfx/gl/SurfaceTypes.cpp new file mode 100644 index 0000000000..9c3e8a2e14 --- /dev/null +++ b/gfx/gl/SurfaceTypes.cpp @@ -0,0 +1,44 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "SurfaceTypes.h" + +#include "mozilla/layers/TextureForwarder.h" + +namespace mozilla { +namespace gl { + +SurfaceCaps::SurfaceCaps() +{ + Clear(); +} + +/* These are defined out of line so that we don't need to include + * ISurfaceAllocator.h in the header */ +SurfaceCaps::SurfaceCaps(const SurfaceCaps& other) = default; +SurfaceCaps& +SurfaceCaps::operator=(const SurfaceCaps& other) = default; + +void +SurfaceCaps::Clear() +{ + any = false; + color = false; + alpha = false; + bpp16 = false; + depth = false; + stencil = false; + antialias = false; + premultAlpha = true; + preserve = false; + surfaceAllocator = nullptr; +} + +SurfaceCaps::~SurfaceCaps() +{ +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/SurfaceTypes.h b/gfx/gl/SurfaceTypes.h new file mode 100644 index 0000000000..aae21e0a9f --- /dev/null +++ b/gfx/gl/SurfaceTypes.h @@ -0,0 +1,98 @@ +/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */ +/* 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 "mozilla/RefPtr.h" +#include "mozilla/Attributes.h" +#include <stdint.h> + +namespace mozilla { +namespace layers { +class LayersIPCChannel; +} // namespace layers + +namespace gl { + +struct SurfaceCaps final +{ + bool any; + bool color, alpha; + bool bpp16; + bool depth, stencil; + bool antialias; + bool premultAlpha; + bool preserve; + + // The surface allocator that we want to create this + // for. May be null. + RefPtr<layers::LayersIPCChannel> surfaceAllocator; + + SurfaceCaps(); + SurfaceCaps(const SurfaceCaps& other); + ~SurfaceCaps(); + + void Clear(); + + SurfaceCaps& operator=(const SurfaceCaps& other); + + // We can't use just 'RGB' here, since it's an ancient Windows macro. + static SurfaceCaps ForRGB() { + SurfaceCaps caps; + + caps.color = true; + + return caps; + } + + static SurfaceCaps ForRGBA() { + SurfaceCaps caps; + + caps.color = true; + caps.alpha = true; + + return caps; + } + + static SurfaceCaps Any() { + SurfaceCaps caps; + + caps.any = true; + + return caps; + } +}; + +enum class SharedSurfaceType : uint8_t { + Unknown = 0, + + Basic, + EGLImageShare, + EGLSurfaceANGLE, + DXGLInterop, + DXGLInterop2, + Gralloc, + IOSurface, + GLXDrawable, + SharedGLTexture, + + Max +}; + +enum class AttachmentType : uint8_t { + Screen = 0, + + GLTexture, + GLRenderbuffer, + + Max +}; + +} // namespace gl + +} /* namespace mozilla */ + +#endif /* SURFACE_TYPES_H_ */ diff --git a/gfx/gl/TextureGarbageBin.cpp b/gfx/gl/TextureGarbageBin.cpp new file mode 100644 index 0000000000..89a9c83553 --- /dev/null +++ b/gfx/gl/TextureGarbageBin.cpp @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 "TextureGarbageBin.h" +#include "GLContext.h" + +using namespace mozilla; +using namespace mozilla::gl; + +void +TextureGarbageBin::GLContextTeardown() +{ + EmptyGarbage(); + + MutexAutoLock lock(mMutex); + mGL = nullptr; +} + +void +TextureGarbageBin::Trash(GLuint tex) +{ + MutexAutoLock lock(mMutex); + if (!mGL) + return; + + mGarbageTextures.push(tex); +} + +void +TextureGarbageBin::EmptyGarbage() +{ + MutexAutoLock lock(mMutex); + if (!mGL) + return; + + MOZ_RELEASE_ASSERT(mGL->IsCurrent(), "GFX: GL context not current."); + while (!mGarbageTextures.empty()) { + GLuint tex = mGarbageTextures.top(); + mGarbageTextures.pop(); + mGL->fDeleteTextures(1, &tex); + } +} diff --git a/gfx/gl/TextureGarbageBin.h b/gfx/gl/TextureGarbageBin.h new file mode 100644 index 0000000000..9218c4f265 --- /dev/null +++ b/gfx/gl/TextureGarbageBin.h @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim: set ts=8 sts=4 et sw=4 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 TEXTUREGARBAGEBIN_H_ +#define TEXTUREGARBAGEBIN_H_ + +#include <stack> + +#include "mozilla/Mutex.h" +#include "nsISupportsImpl.h" + +#include "GLContextTypes.h" + +namespace mozilla { +namespace gl { + +class TextureGarbageBin final { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureGarbageBin) + +private: + // Private destructor, to discourage deletion outside of Release(): + ~TextureGarbageBin() + { + } + + GLContext* mGL; + Mutex mMutex; + std::stack<GLuint> mGarbageTextures; + +public: + explicit TextureGarbageBin(GLContext* gl) + : mGL(gl) + , mMutex("TextureGarbageBin mutex") + {} + + void GLContextTeardown(); + void Trash(GLuint tex); + void EmptyGarbage(); +}; + +} // namespace gl +} // namespace mozilla + +#endif // TEXTUREGARBAGEBIN_H_ diff --git a/gfx/gl/TextureImageEGL.cpp b/gfx/gl/TextureImageEGL.cpp new file mode 100644 index 0000000000..87a547c269 --- /dev/null +++ b/gfx/gl/TextureImageEGL.cpp @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "TextureImageEGL.h" +#include "GLLibraryEGL.h" +#include "GLContext.h" +#include "GLUploadHelpers.h" +#include "gfxPlatform.h" +#include "mozilla/gfx/Types.h" + +namespace mozilla { +namespace gl { + +static GLenum +GLFormatForImage(gfx::SurfaceFormat aFormat) +{ + switch (aFormat) { + case gfx::SurfaceFormat::B8G8R8A8: + case gfx::SurfaceFormat::B8G8R8X8: + return LOCAL_GL_RGBA; + case gfx::SurfaceFormat::R5G6B5_UINT16: + return LOCAL_GL_RGB; + case gfx::SurfaceFormat::A8: + return LOCAL_GL_LUMINANCE; + default: + NS_WARNING("Unknown GL format for Surface format"); + } + return 0; +} + +static GLenum +GLTypeForImage(gfx::SurfaceFormat aFormat) +{ + switch (aFormat) { + case gfx::SurfaceFormat::B8G8R8A8: + case gfx::SurfaceFormat::B8G8R8X8: + case gfx::SurfaceFormat::A8: + return LOCAL_GL_UNSIGNED_BYTE; + case gfx::SurfaceFormat::R5G6B5_UINT16: + return LOCAL_GL_UNSIGNED_SHORT_5_6_5; + default: + NS_WARNING("Unknown GL format for Surface format"); + } + return 0; +} + +TextureImageEGL::TextureImageEGL(GLuint aTexture, + const gfx::IntSize& aSize, + GLenum aWrapMode, + ContentType aContentType, + GLContext* aContext, + Flags aFlags, + TextureState aTextureState, + TextureImage::ImageFormat aImageFormat) + : TextureImage(aSize, aWrapMode, aContentType, aFlags) + , mGLContext(aContext) + , mUpdateFormat(gfx::ImageFormatToSurfaceFormat(aImageFormat)) + , mEGLImage(nullptr) + , mTexture(aTexture) + , mSurface(nullptr) + , mConfig(nullptr) + , mTextureState(aTextureState) + , mBound(false) +{ + if (mUpdateFormat == gfx::SurfaceFormat::UNKNOWN) { + mUpdateFormat = + gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType()); + } + + if (mUpdateFormat == gfx::SurfaceFormat::R5G6B5_UINT16) { + mTextureFormat = gfx::SurfaceFormat::R8G8B8X8; + } else if (mUpdateFormat == gfx::SurfaceFormat::B8G8R8X8) { + mTextureFormat = gfx::SurfaceFormat::B8G8R8X8; + } else { + mTextureFormat = gfx::SurfaceFormat::B8G8R8A8; + } +} + +TextureImageEGL::~TextureImageEGL() +{ + if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) { + return; + } + + // 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 (mGLContext->MakeCurrent()) { + mGLContext->fDeleteTextures(1, &mTexture); + } + ReleaseTexImage(); + DestroyEGLSurface(); +} + +bool +TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom /* = gfx::IntPoint(0,0) */) +{ + gfx::IntRect bounds = aRegion.GetBounds(); + + nsIntRegion region; + if (mTextureState != Valid) { + bounds = gfx::IntRect(0, 0, mSize.width, mSize.height); + region = nsIntRegion(bounds); + } else { + region = aRegion; + } + + bool needInit = mTextureState == Created; + size_t uploadSize = 0; + mTextureFormat = + UploadSurfaceToTexture(mGLContext, + aSurf, + region, + mTexture, + mSize, + &uploadSize, + needInit, + aFrom); + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); + } + + mTextureState = Valid; + return true; +} + +void +TextureImageEGL::BindTexture(GLenum aTextureUnit) +{ + // Ensure the texture is allocated before it is used. + if (mTextureState == Created) { + Resize(mSize); + } + + mGLContext->fActiveTexture(aTextureUnit); + mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); + mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0); +} + +void +TextureImageEGL::Resize(const gfx::IntSize& aSize) +{ + if (mSize == aSize && mTextureState != Created) + return; + + mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture); + + mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D, + 0, + GLFormatForImage(mUpdateFormat), + aSize.width, + aSize.height, + 0, + GLFormatForImage(mUpdateFormat), + GLTypeForImage(mUpdateFormat), + nullptr); + + mTextureState = Allocated; + mSize = aSize; +} + +bool +TextureImageEGL::BindTexImage() +{ + if (mBound && !ReleaseTexImage()) + return false; + + EGLBoolean success = + sEGLLibrary.fBindTexImage(EGL_DISPLAY(), + (EGLSurface)mSurface, + LOCAL_EGL_BACK_BUFFER); + + if (success == LOCAL_EGL_FALSE) + return false; + + mBound = true; + return true; +} + +bool +TextureImageEGL::ReleaseTexImage() +{ + if (!mBound) + return true; + + EGLBoolean success = + sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(), + (EGLSurface)mSurface, + LOCAL_EGL_BACK_BUFFER); + + if (success == LOCAL_EGL_FALSE) + return false; + + mBound = false; + return true; +} + +void +TextureImageEGL::DestroyEGLSurface(void) +{ + if (!mSurface) + return; + + sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface); + mSurface = nullptr; +} + +already_AddRefed<TextureImage> +CreateTextureImageEGL(GLContext* gl, + const gfx::IntSize& aSize, + TextureImage::ContentType aContentType, + GLenum aWrapMode, + TextureImage::Flags aFlags, + TextureImage::ImageFormat aImageFormat) +{ + RefPtr<TextureImage> t = new gl::TiledTextureImage(gl, aSize, aContentType, aFlags, aImageFormat); + return t.forget(); +} + +already_AddRefed<TextureImage> +TileGenFuncEGL(GLContext* gl, + const gfx::IntSize& aSize, + TextureImage::ContentType aContentType, + TextureImage::Flags aFlags, + TextureImage::ImageFormat aImageFormat) +{ + gl->MakeCurrent(); + + GLuint texture; + gl->fGenTextures(1, &texture); + + RefPtr<TextureImageEGL> teximage = + new TextureImageEGL(texture, aSize, LOCAL_GL_CLAMP_TO_EDGE, aContentType, + gl, aFlags, TextureImage::Created, aImageFormat); + + teximage->BindTexture(LOCAL_GL_TEXTURE0); + + GLint texfilter = aFlags & TextureImage::UseNearestFilter ? LOCAL_GL_NEAREST : LOCAL_GL_LINEAR; + gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter); + gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter); + gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE); + gl->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE); + + return teximage.forget(); +} + +} // namespace gl +} // namespace mozilla diff --git a/gfx/gl/TextureImageEGL.h b/gfx/gl/TextureImageEGL.h new file mode 100644 index 0000000000..fa7075064a --- /dev/null +++ b/gfx/gl/TextureImageEGL.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 TEXTUREIMAGEEGL_H_ +#define TEXTUREIMAGEEGL_H_ + +#include "GLTextureImage.h" + +namespace mozilla { +namespace gl { + +class TextureImageEGL final + : public TextureImage +{ +public: + TextureImageEGL(GLuint aTexture, + const gfx::IntSize& aSize, + GLenum aWrapMode, + ContentType aContentType, + GLContext* aContext, + Flags aFlags = TextureImage::NoFlags, + TextureState aTextureState = Created, + TextureImage::ImageFormat aImageFormat = SurfaceFormat::UNKNOWN); + + virtual ~TextureImageEGL(); + + virtual bool DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& aRegion, const gfx::IntPoint& aFrom = gfx::IntPoint(0,0)); + + virtual void BindTexture(GLenum aTextureUnit); + + virtual GLuint GetTextureID() + { + // Ensure the texture is allocated before it is used. + if (mTextureState == Created) { + Resize(mSize); + } + return mTexture; + }; + + virtual void Resize(const gfx::IntSize& aSize); + + bool BindTexImage(); + + bool ReleaseTexImage(); + + virtual bool CreateEGLSurface(gfxASurface* aSurface) + { + return false; + } + + virtual void DestroyEGLSurface(void); + +protected: + typedef gfxImageFormat ImageFormat; + + GLContext* mGLContext; + + gfx::SurfaceFormat mUpdateFormat; + EGLImage mEGLImage; + GLuint mTexture; + EGLSurface mSurface; + EGLConfig mConfig; + TextureState mTextureState; + + bool mBound; +}; + +already_AddRefed<TextureImage> +CreateTextureImageEGL(GLContext* gl, + const gfx::IntSize& aSize, + TextureImage::ContentType aContentType, + GLenum aWrapMode, + TextureImage::Flags aFlags, + TextureImage::ImageFormat aImageFormat); + +already_AddRefed<TextureImage> +TileGenFuncEGL(GLContext* gl, + const gfx::IntSize& aSize, + TextureImage::ContentType aContentType, + TextureImage::Flags aFlags, + TextureImage::ImageFormat aImageFormat); + +} // namespace gl +} // namespace mozilla + +#endif // TEXTUREIMAGEEGL_H_ diff --git a/gfx/gl/WGLLibrary.h b/gfx/gl/WGLLibrary.h new file mode 100644 index 0000000000..3c261e10d9 --- /dev/null +++ b/gfx/gl/WGLLibrary.h @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 "GLContextTypes.h" +#include <windows.h> + +struct PRLibrary; + +namespace mozilla { +namespace gl { + +class WGLLibrary +{ +public: + WGLLibrary() + : mInitialized(false) + , mOGLLibrary(nullptr) + , mHasRobustness(false) + , mHasDXInterop(false) + , mHasDXInterop2(false) + , mWindow (0) + , mWindowDC(0) + , mWindowGLContext(0) + , mWindowPixelFormat(0) + {} + + typedef HGLRC (GLAPIENTRY * PFNWGLCREATECONTEXTPROC) (HDC); + PFNWGLCREATECONTEXTPROC fCreateContext; + typedef BOOL (GLAPIENTRY * PFNWGLDELETECONTEXTPROC) (HGLRC); + PFNWGLDELETECONTEXTPROC fDeleteContext; + typedef BOOL (GLAPIENTRY * PFNWGLMAKECURRENTPROC) (HDC, HGLRC); + PFNWGLMAKECURRENTPROC fMakeCurrent; + typedef PROC (GLAPIENTRY * PFNWGLGETPROCADDRESSPROC) (LPCSTR); + PFNWGLGETPROCADDRESSPROC fGetProcAddress; + typedef HGLRC (GLAPIENTRY * PFNWGLGETCURRENTCONTEXT) (void); + PFNWGLGETCURRENTCONTEXT fGetCurrentContext; + typedef HDC (GLAPIENTRY * PFNWGLGETCURRENTDC) (void); + PFNWGLGETCURRENTDC fGetCurrentDC; + typedef BOOL (GLAPIENTRY * PFNWGLSHARELISTS) (HGLRC oldContext, HGLRC newContext); + PFNWGLSHARELISTS fShareLists; + + typedef HANDLE (WINAPI * PFNWGLCREATEPBUFFERPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int* piAttribList); + PFNWGLCREATEPBUFFERPROC fCreatePbuffer; + typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERPROC) (HANDLE hPbuffer); + PFNWGLDESTROYPBUFFERPROC fDestroyPbuffer; + typedef HDC (WINAPI * PFNWGLGETPBUFFERDCPROC) (HANDLE hPbuffer); + PFNWGLGETPBUFFERDCPROC fGetPbufferDC; + + typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEPROC) (HANDLE hPbuffer, int iBuffer); + PFNWGLBINDTEXIMAGEPROC fBindTexImage; + typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEPROC) (HANDLE hPbuffer, int iBuffer); + PFNWGLRELEASETEXIMAGEPROC fReleaseTexImage; + + typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATPROC) (HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); + PFNWGLCHOOSEPIXELFORMATPROC fChoosePixelFormat; + typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int* piAttributes, int* piValues); + PFNWGLGETPIXELFORMATATTRIBIVPROC fGetPixelFormatAttribiv; + + typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGPROC) (HDC hdc); + PFNWGLGETEXTENSIONSSTRINGPROC fGetExtensionsString; + + typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSPROC) (HDC hdc, HGLRC hShareContext, const int* attribList); + PFNWGLCREATECONTEXTATTRIBSPROC fCreateContextAttribs; + + // WGL_NV_DX_interop: + // BOOL wglDXSetResourceShareHandleNV(void* dxObject, HANDLE shareHandle); + typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLEPROC) (void* dxObject, HANDLE shareHandle); + PFNWGLDXSETRESOURCESHAREHANDLEPROC fDXSetResourceShareHandle; + + // HANDLE wglDXOpenDeviceNV(void* dxDevice); + typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICEPROC) (void* dxDevice); + PFNWGLDXOPENDEVICEPROC fDXOpenDevice; + + // BOOL wglDXCloseDeviceNV(HANDLE hDevice); + typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICEPROC) (HANDLE hDevice); + PFNWGLDXCLOSEDEVICEPROC fDXCloseDevice; + + // HANDLE wglDXRegisterObjectNV(HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); + typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTPROC) (HANDLE hDevice, void* dxObject, GLuint name, GLenum type, GLenum access); + PFNWGLDXREGISTEROBJECTPROC fDXRegisterObject; + + // BOOL wglDXUnregisterObjectNV(HANDLE hDevice, HANDLE hObject); + typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECT) (HANDLE hDevice, HANDLE hObject); + PFNWGLDXUNREGISTEROBJECT fDXUnregisterObject; + + // BOOL wglDXObjectAccessNV(HANDLE hObject, GLenum access); + typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSPROC) (HANDLE hObject, GLenum access); + PFNWGLDXOBJECTACCESSPROC fDXObjectAccess; + + // BOOL wglDXLockObjectsNV(HANDLE hDevice, GLint count, HANDLE* hObjects); + typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); + PFNWGLDXLOCKOBJECTSPROC fDXLockObjects; + + // BOOL wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, HANDLE* hObjects); + typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSPROC) (HANDLE hDevice, GLint count, HANDLE* hObjects); + PFNWGLDXUNLOCKOBJECTSPROC fDXUnlockObjects; + + bool EnsureInitialized(); + HWND CreateDummyWindow(HDC* aWindowDC = nullptr); + + bool HasRobustness() const { return mHasRobustness; } + bool HasDXInterop() const { return mHasDXInterop; } + bool HasDXInterop2() const { return mHasDXInterop2; } + bool IsInitialized() const { return mInitialized; } + HWND GetWindow() const { return mWindow; } + HDC GetWindowDC() const {return mWindowDC; } + HGLRC GetWindowGLContext() const {return mWindowGLContext; } + int GetWindowPixelFormat() const { return mWindowPixelFormat; } + PRLibrary* GetOGLLibrary() { return mOGLLibrary; } + +private: + bool mInitialized; + PRLibrary* mOGLLibrary; + bool mHasRobustness; + bool mHasDXInterop; + bool mHasDXInterop2; + + HWND mWindow; + HDC mWindowDC; + HGLRC mWindowGLContext; + int mWindowPixelFormat; + +}; + +// a global WGLLibrary instance +extern WGLLibrary sWGLLib; + +} /* namespace gl */ +} /* namespace mozilla */ diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build new file mode 100644 index 0000000000..596612bb8e --- /dev/null +++ b/gfx/gl/moz.build @@ -0,0 +1,164 @@ +# -*- 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 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']: + gl_provider = 'EGL' + else: + gl_provider = 'GLX' +elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': + gl_provider = 'EGL' + +if CONFIG['MOZ_GL_PROVIDER']: + gl_provider = CONFIG['MOZ_GL_PROVIDER'] + +EXPORTS += [ + 'AndroidSurfaceTexture.h', + 'DecomposeIntoNoRepeatTriangles.h', + 'EGLUtils.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', + 'ScopedGLHelpers.h', + 'SharedSurface.h', + 'SharedSurfaceEGL.h', + 'SharedSurfaceGL.h', + 'SurfaceTypes.h', + 'TextureGarbageBin.h', +] + +if CONFIG['MOZ_X11']: + EXPORTS += [ + 'GLContextGLX.h', + 'GLXLibrary.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 += [ + 'GLContextProviderWGL.cpp', + 'SharedSurfaceANGLE.cpp', + 'SharedSurfaceD3D11Interop.cpp', + ] +if CONFIG['MOZ_ENABLE_SKIA_GPU']: + EXPORTS += ['SkiaGLGlue.h'] + SOURCES += [ + 'SkiaGLGlue.cpp', + ] + if CONFIG['CLANG_CXX']: + # Suppress warnings from Skia header files. + SOURCES['SkiaGLGlue.cpp'].flags += ['-Wno-implicit-fallthrough'] + +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', + ] +elif gl_provider == 'EAGL': + # These files include ObjC headers that are unfriendly to unified builds + SOURCES += [ + 'GLContextProviderEAGL.mm', + ] + EXPORTS += [ + 'GLContextEAGL.h', + ] + +elif gl_provider == 'GLX': + # GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES + # as it includes X11 headers which cause conflicts. + SOURCES += [ + 'GLContextProviderGLX.cpp', + 'SharedSurfaceGLX.cpp' + ] + EXPORTS += [ + 'SharedSurfaceGLX.h' + ] + +UNIFIED_SOURCES += [ + 'AndroidSurfaceTexture.cpp', + 'DecomposeIntoNoRepeatTriangles.cpp', + 'EGLUtils.cpp', + 'GfxTexturesReporter.cpp', + 'GLBlitHelper.cpp', + 'GLContext.cpp', + 'GLContextFeatures.cpp', + 'GLContextProviderEGL.cpp', + 'GLContextTypes.cpp', + 'GLDebugUtils.cpp', + 'GLLibraryEGL.cpp', + 'GLLibraryLoader.cpp', + 'GLReadTexImageHelper.cpp', + 'GLScreenBuffer.cpp', + 'GLTextureImage.cpp', + 'GLUploadHelpers.cpp', + 'ScopedGLHelpers.cpp', + 'SharedSurface.cpp', + 'SharedSurfaceEGL.cpp', + 'SharedSurfaceGL.cpp', + 'SurfaceTypes.cpp', + 'TextureGarbageBin.cpp', + 'TextureImageEGL.cpp', +] + +include('/ipc/chromium/chromium-config.mozbuild') + +FINAL_LIBRARY = 'xul' + +if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']: + DEFINES['MOZ_D3DCOMPILER_VISTA_DLL'] = CONFIG['MOZ_D3DCOMPILER_VISTA_DLL'] +if CONFIG['MOZ_D3DCOMPILER_XP_DLL']: + DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL'] + +CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] +CXXFLAGS += CONFIG['TK_CFLAGS'] +CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] +CFLAGS += CONFIG['TK_CFLAGS'] + +LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES'] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] |