summaryrefslogtreecommitdiffstats
path: root/gfx/gl/GLContext.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /gfx/gl/GLContext.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/gl/GLContext.h')
-rw-r--r--gfx/gl/GLContext.h3736
1 files changed, 3736 insertions, 0 deletions
diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h
new file mode 100644
index 000000000..f20563070
--- /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_ */