diff options
Diffstat (limited to 'gfx/gl/GLContext.h')
-rw-r--r-- | gfx/gl/GLContext.h | 3736 |
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_ */ |