mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
3881 lines
110 KiB
C++
3881 lines
110 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef GLCONTEXT_H_
|
|
#define GLCONTEXT_H_
|
|
|
|
#include <bitset>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stack>
|
|
#include <vector>
|
|
|
|
#ifdef DEBUG
|
|
# include <string.h>
|
|
#endif
|
|
|
|
#ifdef GetClassName
|
|
# undef GetClassName
|
|
#endif
|
|
|
|
// Define MOZ_GL_DEBUG_BUILD unconditionally to enable GL debugging in opt
|
|
// builds.
|
|
#ifdef DEBUG
|
|
# define MOZ_GL_DEBUG_BUILD 1
|
|
#endif
|
|
|
|
#include "mozilla/IntegerRange.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "mozilla/UniquePtr.h"
|
|
#include "mozilla/ThreadLocal.h"
|
|
|
|
#include "MozFramebuffer.h"
|
|
#include "nsTArray.h"
|
|
#include "GLConsts.h"
|
|
#include "GLDefs.h"
|
|
#include "GLTypes.h"
|
|
#include "GLVendor.h"
|
|
#include "nsRegionFwd.h"
|
|
#include "nsString.h"
|
|
#include "GLContextTypes.h"
|
|
#include "GLContextSymbols.h"
|
|
#include "base/platform_thread.h" // for PlatformThreadId
|
|
#include "mozilla/GenericRefCounted.h"
|
|
#include "mozilla/WeakPtr.h"
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
# include "mozilla/ProfilerLabels.h"
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
|
|
namespace gl {
|
|
class GLBlitHelper;
|
|
class GLLibraryEGL;
|
|
class GLReadTexImageHelper;
|
|
class SharedSurface;
|
|
class SymbolLoader;
|
|
struct SymLoadStruct;
|
|
} // namespace gl
|
|
|
|
namespace layers {
|
|
class ColorTextureLayerProgram;
|
|
} // namespace layers
|
|
|
|
namespace widget {
|
|
class CompositorWidget;
|
|
} // namespace widget
|
|
} // namespace mozilla
|
|
|
|
namespace mozilla {
|
|
namespace gl {
|
|
|
|
enum class GLFeature {
|
|
bind_buffer_offset,
|
|
blend_minmax,
|
|
clear_buffers,
|
|
copy_buffer,
|
|
depth_texture,
|
|
draw_buffers,
|
|
draw_buffers_indexed,
|
|
draw_instanced,
|
|
element_index_uint,
|
|
ES2_compatibility,
|
|
ES3_compatibility,
|
|
EXT_color_buffer_float,
|
|
frag_color_float,
|
|
frag_depth,
|
|
framebuffer_blit,
|
|
framebuffer_multisample,
|
|
framebuffer_object,
|
|
framebuffer_object_EXT_OES,
|
|
get_integer_indexed,
|
|
get_integer64_indexed,
|
|
get_query_object_i64v,
|
|
get_query_object_iv,
|
|
gpu_shader4,
|
|
instanced_arrays,
|
|
instanced_non_arrays,
|
|
internalformat_query,
|
|
invalidate_framebuffer,
|
|
map_buffer_range,
|
|
multiview,
|
|
occlusion_query,
|
|
occlusion_query_boolean,
|
|
occlusion_query2,
|
|
packed_depth_stencil,
|
|
prim_restart,
|
|
prim_restart_fixed,
|
|
provoking_vertex,
|
|
query_counter,
|
|
query_objects,
|
|
query_time_elapsed,
|
|
read_buffer,
|
|
renderbuffer_color_float,
|
|
renderbuffer_color_half_float,
|
|
robust_buffer_access_behavior,
|
|
robustness,
|
|
sRGB,
|
|
sampler_objects,
|
|
seamless_cube_map_opt_in,
|
|
shader_texture_lod,
|
|
split_framebuffer,
|
|
standard_derivatives,
|
|
sync,
|
|
texture_3D,
|
|
texture_3D_compressed,
|
|
texture_3D_copy,
|
|
texture_compression_bptc,
|
|
texture_compression_rgtc,
|
|
texture_float,
|
|
texture_float_linear,
|
|
texture_half_float,
|
|
texture_half_float_linear,
|
|
texture_non_power_of_two,
|
|
texture_norm16,
|
|
texture_rg,
|
|
texture_storage,
|
|
texture_swizzle,
|
|
transform_feedback2,
|
|
uniform_buffer_object,
|
|
uniform_matrix_nonsquare,
|
|
vertex_array_object,
|
|
EnumMax
|
|
};
|
|
|
|
enum class ContextProfile : uint8_t {
|
|
Unknown = 0,
|
|
OpenGLCore,
|
|
OpenGLCompatibility,
|
|
OpenGLES
|
|
};
|
|
|
|
enum class GLRenderer {
|
|
Adreno200,
|
|
Adreno205,
|
|
AdrenoTM200,
|
|
AdrenoTM205,
|
|
AdrenoTM305,
|
|
AdrenoTM320,
|
|
AdrenoTM330,
|
|
AdrenoTM420,
|
|
Mali400MP,
|
|
Mali450MP,
|
|
MaliT,
|
|
SGX530,
|
|
SGX540,
|
|
SGX544MP,
|
|
Tegra,
|
|
AndroidEmulator,
|
|
GalliumLlvmpipe,
|
|
IntelHD3000,
|
|
MicrosoftBasicRenderDriver,
|
|
Other
|
|
};
|
|
|
|
class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
|
|
public:
|
|
static MOZ_THREAD_LOCAL(const GLContext*) sCurrentContext;
|
|
|
|
const GLContextDesc mDesc;
|
|
|
|
bool mImplicitMakeCurrent = false;
|
|
bool mUseTLSIsCurrent;
|
|
|
|
class TlsScope final {
|
|
const WeakPtr<GLContext> mGL;
|
|
const bool mWasTlsOk;
|
|
|
|
public:
|
|
explicit TlsScope(GLContext* const gl)
|
|
: mGL(gl), mWasTlsOk(gl && gl->mUseTLSIsCurrent) {
|
|
if (mGL) {
|
|
mGL->mUseTLSIsCurrent = true;
|
|
}
|
|
}
|
|
|
|
~TlsScope() {
|
|
if (mGL) {
|
|
mGL->mUseTLSIsCurrent = mWasTlsOk;
|
|
}
|
|
}
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// basic getters
|
|
public:
|
|
/**
|
|
* Returns true if the context is using ANGLE. This should only be overridden
|
|
* for an ANGLE implementation.
|
|
*/
|
|
virtual bool IsANGLE() const { return false; }
|
|
|
|
/**
|
|
* Returns true if the context is using WARP. This should only be overridden
|
|
* for an ANGLE implementation.
|
|
*/
|
|
virtual bool IsWARP() const { return false; }
|
|
|
|
virtual void GetWSIInfo(nsCString* const out) const = 0;
|
|
|
|
/**
|
|
* Return true if we are running on a OpenGL core profile context
|
|
*/
|
|
inline bool IsCoreProfile() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLCore;
|
|
}
|
|
|
|
/**
|
|
* Return true if we are running on a OpenGL compatibility profile context
|
|
* (legacy profile 2.1 on Max OS X)
|
|
*/
|
|
inline bool IsCompatibilityProfile() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLCompatibility;
|
|
}
|
|
|
|
inline bool IsGLES() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLES;
|
|
}
|
|
|
|
inline bool IsAtLeast(ContextProfile profile, unsigned int version) const {
|
|
MOZ_ASSERT(profile != ContextProfile::Unknown,
|
|
"IsAtLeast: bad <profile> parameter");
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
MOZ_ASSERT(mVersion != 0, "unknown context version");
|
|
|
|
if (version > mVersion) {
|
|
return false;
|
|
}
|
|
|
|
return profile == mProfile;
|
|
}
|
|
|
|
/**
|
|
* Return the version of the context.
|
|
* Example :
|
|
* If this a OpenGL 2.1, that will return 210
|
|
*/
|
|
inline uint32_t Version() const { return mVersion; }
|
|
|
|
inline uint32_t ShadingLanguageVersion() const {
|
|
return mShadingLanguageVersion;
|
|
}
|
|
|
|
GLVendor Vendor() const { return mVendor; }
|
|
GLRenderer Renderer() const { return mRenderer; }
|
|
bool IsMesa() const { return mIsMesa; }
|
|
|
|
bool IsContextLost() const { return mContextLost; }
|
|
|
|
bool CheckContextLost() const {
|
|
mTopError = GetError();
|
|
return IsContextLost();
|
|
}
|
|
|
|
bool HasPBOState() const { return (!IsGLES() || Version() >= 300); }
|
|
|
|
/**
|
|
* If this context is double-buffered, returns TRUE.
|
|
*/
|
|
virtual bool IsDoubleBuffered() const { return false; }
|
|
|
|
virtual GLContextType GetContextType() const = 0;
|
|
|
|
virtual bool IsCurrentImpl() const = 0;
|
|
virtual bool MakeCurrentImpl() const = 0;
|
|
|
|
bool IsCurrent() const {
|
|
if (mImplicitMakeCurrent) return MakeCurrent();
|
|
|
|
return IsCurrentImpl();
|
|
}
|
|
|
|
bool MakeCurrent(bool aForce = false) const;
|
|
|
|
/**
|
|
* Get the default framebuffer for this context.
|
|
*/
|
|
UniquePtr<MozFramebuffer> mOffscreenDefaultFb;
|
|
|
|
bool CreateOffscreenDefaultFb(const gfx::IntSize& size);
|
|
|
|
virtual GLuint GetDefaultFramebuffer() {
|
|
if (mOffscreenDefaultFb) {
|
|
return mOffscreenDefaultFb->mFB;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* mVersion store the OpenGL's version, multiplied by 100. For example, if
|
|
* the context is an OpenGL 2.1 context, mVersion value will be 210.
|
|
*/
|
|
uint32_t mVersion = 0;
|
|
ContextProfile mProfile = ContextProfile::Unknown;
|
|
|
|
uint32_t mShadingLanguageVersion = 0;
|
|
|
|
GLVendor mVendor = GLVendor::Other;
|
|
GLRenderer mRenderer = GLRenderer::Other;
|
|
bool mIsMesa = false;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extensions management
|
|
/**
|
|
* This mechanism is designed to know if an extension is supported. In the
|
|
* long term, we would like to only use the extension group queries XXX_* to
|
|
* have full compatibility with context version and profiles (especialy the
|
|
* core that officialy don't bring any extensions).
|
|
*/
|
|
|
|
/**
|
|
* Known GL extensions that can be queried by
|
|
* IsExtensionSupported. The results of this are cached, and as
|
|
* such it's safe to use this even in performance critical code.
|
|
* If you add to this array, remember to add to the string names
|
|
* in GLContext.cpp.
|
|
*/
|
|
enum GLExtensions {
|
|
Extension_None = 0,
|
|
AMD_compressed_ATC_texture,
|
|
ANGLE_depth_texture,
|
|
ANGLE_framebuffer_blit,
|
|
ANGLE_framebuffer_multisample,
|
|
ANGLE_instanced_arrays,
|
|
ANGLE_multiview,
|
|
ANGLE_provoking_vertex,
|
|
ANGLE_texture_compression_dxt3,
|
|
ANGLE_texture_compression_dxt5,
|
|
ANGLE_timer_query,
|
|
APPLE_client_storage,
|
|
APPLE_fence,
|
|
APPLE_framebuffer_multisample,
|
|
APPLE_sync,
|
|
APPLE_texture_range,
|
|
APPLE_vertex_array_object,
|
|
ARB_ES2_compatibility,
|
|
ARB_ES3_compatibility,
|
|
ARB_color_buffer_float,
|
|
ARB_compatibility,
|
|
ARB_copy_buffer,
|
|
ARB_depth_texture,
|
|
ARB_draw_buffers,
|
|
ARB_draw_instanced,
|
|
ARB_framebuffer_object,
|
|
ARB_framebuffer_sRGB,
|
|
ARB_geometry_shader4,
|
|
ARB_half_float_pixel,
|
|
ARB_instanced_arrays,
|
|
ARB_internalformat_query,
|
|
ARB_invalidate_subdata,
|
|
ARB_map_buffer_range,
|
|
ARB_occlusion_query2,
|
|
ARB_pixel_buffer_object,
|
|
ARB_provoking_vertex,
|
|
ARB_robust_buffer_access_behavior,
|
|
ARB_robustness,
|
|
ARB_sampler_objects,
|
|
ARB_seamless_cube_map,
|
|
ARB_shader_texture_lod,
|
|
ARB_sync,
|
|
ARB_texture_compression,
|
|
ARB_texture_compression_bptc,
|
|
ARB_texture_compression_rgtc,
|
|
ARB_texture_float,
|
|
ARB_texture_non_power_of_two,
|
|
ARB_texture_rectangle,
|
|
ARB_texture_rg,
|
|
ARB_texture_storage,
|
|
ARB_texture_swizzle,
|
|
ARB_timer_query,
|
|
ARB_transform_feedback2,
|
|
ARB_uniform_buffer_object,
|
|
ARB_vertex_array_object,
|
|
CHROMIUM_color_buffer_float_rgb,
|
|
CHROMIUM_color_buffer_float_rgba,
|
|
EXT_bgra,
|
|
EXT_blend_minmax,
|
|
EXT_color_buffer_float,
|
|
EXT_color_buffer_half_float,
|
|
EXT_copy_texture,
|
|
EXT_disjoint_timer_query,
|
|
EXT_draw_buffers,
|
|
EXT_draw_buffers2,
|
|
EXT_draw_instanced,
|
|
EXT_float_blend,
|
|
EXT_frag_depth,
|
|
EXT_framebuffer_blit,
|
|
EXT_framebuffer_multisample,
|
|
EXT_framebuffer_object,
|
|
EXT_framebuffer_sRGB,
|
|
EXT_gpu_shader4,
|
|
EXT_map_buffer_range,
|
|
EXT_multisampled_render_to_texture,
|
|
EXT_occlusion_query_boolean,
|
|
EXT_packed_depth_stencil,
|
|
EXT_provoking_vertex,
|
|
EXT_read_format_bgra,
|
|
EXT_robustness,
|
|
EXT_sRGB,
|
|
EXT_sRGB_write_control,
|
|
EXT_shader_texture_lod,
|
|
EXT_texture_compression_bptc,
|
|
EXT_texture_compression_dxt1,
|
|
EXT_texture_compression_rgtc,
|
|
EXT_texture_compression_s3tc,
|
|
EXT_texture_compression_s3tc_srgb,
|
|
EXT_texture_filter_anisotropic,
|
|
EXT_texture_format_BGRA8888,
|
|
EXT_texture_norm16,
|
|
EXT_texture_sRGB,
|
|
EXT_texture_storage,
|
|
EXT_timer_query,
|
|
EXT_transform_feedback,
|
|
EXT_unpack_subimage,
|
|
IMG_read_format,
|
|
IMG_texture_compression_pvrtc,
|
|
IMG_texture_npot,
|
|
KHR_debug,
|
|
KHR_parallel_shader_compile,
|
|
KHR_robust_buffer_access_behavior,
|
|
KHR_robustness,
|
|
KHR_texture_compression_astc_hdr,
|
|
KHR_texture_compression_astc_ldr,
|
|
NV_draw_instanced,
|
|
NV_fence,
|
|
NV_framebuffer_blit,
|
|
NV_geometry_program4,
|
|
NV_half_float,
|
|
NV_instanced_arrays,
|
|
NV_primitive_restart,
|
|
NV_texture_barrier,
|
|
NV_transform_feedback,
|
|
NV_transform_feedback2,
|
|
OES_EGL_image,
|
|
OES_EGL_image_external,
|
|
OES_EGL_sync,
|
|
OES_compressed_ETC1_RGB8_texture,
|
|
OES_depth24,
|
|
OES_depth32,
|
|
OES_depth_texture,
|
|
OES_draw_buffers_indexed,
|
|
OES_element_index_uint,
|
|
OES_fbo_render_mipmap,
|
|
OES_framebuffer_object,
|
|
OES_packed_depth_stencil,
|
|
OES_rgb8_rgba8,
|
|
OES_standard_derivatives,
|
|
OES_stencil8,
|
|
OES_texture_3D,
|
|
OES_texture_float,
|
|
OES_texture_float_linear,
|
|
OES_texture_half_float,
|
|
OES_texture_half_float_linear,
|
|
OES_texture_npot,
|
|
OES_vertex_array_object,
|
|
OVR_multiview2,
|
|
Extensions_Max,
|
|
Extensions_End
|
|
};
|
|
|
|
bool IsExtensionSupported(GLExtensions aKnownExtension) const {
|
|
return mAvailableExtensions[aKnownExtension];
|
|
}
|
|
|
|
protected:
|
|
void MarkExtensionUnsupported(GLExtensions aKnownExtension) {
|
|
mAvailableExtensions[aKnownExtension] = 0;
|
|
}
|
|
|
|
void MarkExtensionSupported(GLExtensions aKnownExtension) {
|
|
mAvailableExtensions[aKnownExtension] = 1;
|
|
}
|
|
|
|
std::bitset<Extensions_Max> mAvailableExtensions;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Feature queries
|
|
/*
|
|
* This mecahnism introduces a new way to check if a OpenGL feature is
|
|
* supported, regardless of whether it is supported by an extension or
|
|
* natively by the context version/profile
|
|
*/
|
|
public:
|
|
bool IsSupported(GLFeature feature) const {
|
|
return mAvailableFeatures[size_t(feature)];
|
|
}
|
|
|
|
static const char* GetFeatureName(GLFeature feature);
|
|
|
|
private:
|
|
std::bitset<size_t(GLFeature::EnumMax)> mAvailableFeatures;
|
|
|
|
/**
|
|
* Init features regarding OpenGL extension and context version and profile
|
|
*/
|
|
void InitFeatures();
|
|
|
|
/**
|
|
* Mark the feature and associated extensions as unsupported
|
|
*/
|
|
void MarkUnsupported(GLFeature feature);
|
|
|
|
/**
|
|
* Is this feature supported using the core (unsuffixed) symbols?
|
|
*/
|
|
bool IsFeatureProvidedByCoreSymbols(GLFeature feature);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Error handling
|
|
|
|
private:
|
|
mutable bool mContextLost = false;
|
|
mutable GLenum mTopError = 0;
|
|
|
|
protected:
|
|
void OnContextLostError() const;
|
|
|
|
public:
|
|
static std::string GLErrorToString(GLenum aError);
|
|
|
|
static bool IsBadCallError(const GLenum err) {
|
|
return !(err == 0 || err == LOCAL_GL_CONTEXT_LOST);
|
|
}
|
|
|
|
class LocalErrorScope;
|
|
|
|
private:
|
|
mutable std::stack<const LocalErrorScope*> mLocalErrorScopeStack;
|
|
mutable UniquePtr<LocalErrorScope> mDebugErrorScope;
|
|
|
|
////////////////////////////////////
|
|
// Use this safer option.
|
|
|
|
public:
|
|
class LocalErrorScope {
|
|
const GLContext& mGL;
|
|
GLenum mOldTop;
|
|
bool mHasBeenChecked;
|
|
|
|
public:
|
|
explicit LocalErrorScope(const GLContext& gl)
|
|
: mGL(gl), mHasBeenChecked(false) {
|
|
mGL.mLocalErrorScopeStack.push(this);
|
|
mOldTop = mGL.GetError();
|
|
}
|
|
|
|
/// Never returns CONTEXT_LOST.
|
|
GLenum GetError() {
|
|
MOZ_ASSERT(!mHasBeenChecked);
|
|
mHasBeenChecked = true;
|
|
|
|
const auto ret = mGL.GetError();
|
|
if (ret == LOCAL_GL_CONTEXT_LOST) return 0;
|
|
return ret;
|
|
}
|
|
|
|
~LocalErrorScope() {
|
|
MOZ_ASSERT(mHasBeenChecked);
|
|
|
|
MOZ_ASSERT(!IsBadCallError(mGL.GetError()));
|
|
|
|
MOZ_ASSERT(mGL.mLocalErrorScopeStack.top() == this);
|
|
mGL.mLocalErrorScopeStack.pop();
|
|
|
|
mGL.mTopError = mOldTop;
|
|
}
|
|
};
|
|
|
|
// -
|
|
|
|
bool GetPotentialInteger(GLenum pname, GLint* param) {
|
|
LocalErrorScope localError(*this);
|
|
|
|
fGetIntegerv(pname, param);
|
|
|
|
GLenum err = localError.GetError();
|
|
MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_INVALID_ENUM);
|
|
return err == LOCAL_GL_NO_ERROR;
|
|
}
|
|
|
|
void DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity,
|
|
GLsizei length, const GLchar* message);
|
|
|
|
private:
|
|
static void GLAPIENTRY StaticDebugCallback(GLenum source, GLenum type,
|
|
GLuint id, GLenum severity,
|
|
GLsizei length,
|
|
const GLchar* message,
|
|
const GLvoid* userParam);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Debugging implementation
|
|
private:
|
|
#ifndef MOZ_FUNCTION_NAME
|
|
# ifdef __GNUC__
|
|
# define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
|
|
# elif defined(_MSC_VER)
|
|
# define MOZ_FUNCTION_NAME __FUNCTION__
|
|
# else
|
|
# define MOZ_FUNCTION_NAME \
|
|
__func__ // defined in C99, supported in various C++ compilers. Just raw
|
|
// function name.
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
// Record the name of the GL call for better hang stacks on Android.
|
|
# define ANDROID_ONLY_PROFILER_LABEL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
|
|
#else
|
|
# define ANDROID_ONLY_PROFILER_LABEL
|
|
#endif
|
|
|
|
#define BEFORE_GL_CALL \
|
|
ANDROID_ONLY_PROFILER_LABEL \
|
|
if (MOZ_LIKELY(BeforeGLCall(MOZ_FUNCTION_NAME))) { \
|
|
do { \
|
|
} while (0)
|
|
|
|
#define AFTER_GL_CALL \
|
|
AfterGLCall(MOZ_FUNCTION_NAME); \
|
|
} \
|
|
do { \
|
|
} while (0)
|
|
|
|
void BeforeGLCall_Debug(const char* funcName) const;
|
|
void AfterGLCall_Debug(const char* funcName) const;
|
|
static void OnImplicitMakeCurrentFailure(const char* funcName);
|
|
|
|
bool BeforeGLCall(const char* const funcName) const {
|
|
if (mImplicitMakeCurrent) {
|
|
if (MOZ_UNLIKELY(!MakeCurrent())) {
|
|
if (!mContextLost) {
|
|
OnImplicitMakeCurrentFailure(funcName);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
MOZ_GL_ASSERT(this, IsCurrentImpl());
|
|
|
|
if (MOZ_UNLIKELY(mDebugFlags)) {
|
|
BeforeGLCall_Debug(funcName);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void AfterGLCall(const char* const funcName) const {
|
|
if (MOZ_UNLIKELY(mDebugFlags)) {
|
|
AfterGLCall_Debug(funcName);
|
|
}
|
|
}
|
|
|
|
GLContext* TrackingContext() {
|
|
GLContext* tip = this;
|
|
while (tip->mSharedContext) tip = tip->mSharedContext;
|
|
return tip;
|
|
}
|
|
|
|
static void AssertNotPassingStackBufferToTheGL(const void* ptr);
|
|
|
|
#ifdef MOZ_GL_DEBUG_BUILD
|
|
|
|
# define TRACKING_CONTEXT(a) \
|
|
do { \
|
|
TrackingContext()->a; \
|
|
} while (0)
|
|
|
|
# define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) \
|
|
AssertNotPassingStackBufferToTheGL(ptr)
|
|
|
|
# define ASSERT_SYMBOL_PRESENT(func) \
|
|
do { \
|
|
MOZ_ASSERT(strstr(MOZ_FUNCTION_NAME, #func) != nullptr, \
|
|
"Mismatched symbol check."); \
|
|
if (MOZ_UNLIKELY(!mSymbols.func)) { \
|
|
printf_stderr("RUNTIME ASSERT: Uninitialized GL function: %s\n", \
|
|
#func); \
|
|
MOZ_CRASH("GFX: Uninitialized GL function"); \
|
|
} \
|
|
} while (0)
|
|
|
|
#else // ifdef MOZ_GL_DEBUG_BUILD
|
|
|
|
# define TRACKING_CONTEXT(a) \
|
|
do { \
|
|
} while (0)
|
|
# define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) \
|
|
do { \
|
|
} while (0)
|
|
# define ASSERT_SYMBOL_PRESENT(func) \
|
|
do { \
|
|
} while (0)
|
|
|
|
#endif // ifdef MOZ_GL_DEBUG_BUILD
|
|
|
|
// Do whatever setup is necessary to draw to our offscreen FBO, if it's
|
|
// bound.
|
|
void BeforeGLDrawCall() {}
|
|
|
|
// Do whatever tear-down is necessary after drawing to our offscreen FBO,
|
|
// if it's bound.
|
|
void AfterGLDrawCall() { mHeavyGLCallsSinceLastFlush = true; }
|
|
|
|
// Do whatever setup is necessary to read from our offscreen FBO, if it's
|
|
// bound.
|
|
void BeforeGLReadCall() {}
|
|
|
|
// Do whatever tear-down is necessary after reading from our offscreen FBO,
|
|
// if it's bound.
|
|
void AfterGLReadCall() {}
|
|
|
|
public:
|
|
void OnSyncCall() const { mSyncGLCallCount++; }
|
|
|
|
uint64_t GetSyncCallCount() const { return mSyncGLCallCount; }
|
|
|
|
void ResetSyncCallCount(const char* resetReason) const;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// GL official entry points
|
|
public:
|
|
// We smash all errors together, so you never have to loop on this. We
|
|
// guarantee that immediately after this call, there are no errors left.
|
|
// Always returns the top-most error, except if followed by CONTEXT_LOST, then
|
|
// return that instead.
|
|
GLenum GetError() const;
|
|
|
|
GLenum fGetError() { return GetError(); }
|
|
|
|
GLenum fGetGraphicsResetStatus() const;
|
|
|
|
// -
|
|
|
|
void fActiveTexture(GLenum texture) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fActiveTexture(texture);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fAttachShader(GLuint program, GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fAttachShader(program, shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBeginQuery(GLenum target, GLuint id) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBeginQuery);
|
|
mSymbols.fBeginQuery(target, id);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindAttribLocation(program, index, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindBuffer(GLenum target, GLuint buffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindBuffer(target, buffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
|
|
const GLenum* attachments) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
|
|
mSymbols.fInvalidateFramebuffer(target, numAttachments, attachments);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments,
|
|
const GLenum* attachments, GLint x, GLint y,
|
|
GLsizei width, GLsizei height) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
|
|
mSymbols.fInvalidateSubFramebuffer(target, numAttachments, attachments, x,
|
|
y, width, height);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fBindTexture(GLenum target, GLuint texture) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindTexture(target, texture);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendColor(red, green, blue, alpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendEquation(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendEquation(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendEquationSeparate(modeRGB, modeAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendFunc(GLenum sfactor, GLenum dfactor) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendFunc(sfactor, dfactor);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB,
|
|
GLenum sfactorAlpha, GLenum dfactorAlpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha,
|
|
dfactorAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
|
|
GLenum usage) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(data);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBufferData(target, size, data, usage);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
public:
|
|
void fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data,
|
|
GLenum usage) {
|
|
raw_fBufferData(target, size, data, usage);
|
|
|
|
// bug 744888
|
|
if (WorkAroundDriverBugs() && !data && Vendor() == GLVendor::NVIDIA) {
|
|
UniquePtr<char[]> buf = MakeUnique<char[]>(1);
|
|
buf[0] = 0;
|
|
fBufferSubData(target, size - 1, 1, buf.get());
|
|
}
|
|
}
|
|
|
|
void fBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
|
|
const GLvoid* data) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(data);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBufferSubData(target, offset, size, data);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
private:
|
|
void raw_fClear(GLbitfield mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClear(mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fClear(GLbitfield mask) {
|
|
BeforeGLDrawCall();
|
|
raw_fClear(mask);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth,
|
|
GLint stencil) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearBufferfi(buffer, drawbuffer, depth, stencil);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearBufferfv(buffer, drawbuffer, value);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearBufferiv(buffer, drawbuffer, value);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) {
|
|
BeforeGLDrawCall();
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearBufferuiv(buffer, drawbuffer, value);
|
|
AFTER_GL_CALL;
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearColor(r, g, b, a);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fClearStencil(GLint s) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClearStencil(s);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fClientActiveTexture(GLenum texture) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fClientActiveTexture(texture);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fColorMask(realGLboolean red, realGLboolean green, realGLboolean blue,
|
|
realGLboolean alpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fColorMask(red, green, blue, alpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat,
|
|
GLsizei width, GLsizei height, GLint border,
|
|
GLsizei imageSize, const GLvoid* pixels) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCompressedTexImage2D(target, level, internalformat, width, height,
|
|
border, imageSize, pixels);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
void fCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|
GLint yoffset, GLsizei width, GLsizei height,
|
|
GLenum format, GLsizei imageSize,
|
|
const GLvoid* pixels) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCompressedTexSubImage2D(target, level, xoffset, yoffset, width,
|
|
height, format, imageSize, pixels);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
|
|
GLint x, GLint y, GLsizei width, GLsizei height,
|
|
GLint border);
|
|
|
|
void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|
GLint yoffset, GLint x, GLint y, GLsizei width,
|
|
GLsizei height) {
|
|
BeforeGLReadCall();
|
|
raw_fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
|
|
height);
|
|
AfterGLReadCall();
|
|
}
|
|
|
|
void fCullFace(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCullFace(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageCallback(GLDEBUGPROC callback, const GLvoid* userParam) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageCallback);
|
|
mSymbols.fDebugMessageCallback(callback, userParam);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageControl(GLenum source, GLenum type, GLenum severity,
|
|
GLsizei count, const GLuint* ids,
|
|
realGLboolean enabled) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageControl);
|
|
mSymbols.fDebugMessageControl(source, type, severity, count, ids, enabled);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageInsert(GLenum source, GLenum type, GLuint id,
|
|
GLenum severity, GLsizei length, const GLchar* buf) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageInsert);
|
|
mSymbols.fDebugMessageInsert(source, type, id, severity, length, buf);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDetachShader(GLuint program, GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDetachShader(program, shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDepthFunc(GLenum func) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDepthFunc(func);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDepthMask(realGLboolean flag) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDepthMask(flag);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisable(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisable(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisableClientState(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisableClientState(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisableVertexAttribArray(GLuint index) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisableVertexAttribArray(index);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDrawBuffer(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawBuffer(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawArrays(mode, first, count);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type,
|
|
const GLvoid* indices) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawElements(mode, count, type, indices);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawArrays(mode, first, count);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fDrawElements(GLenum mode, GLsizei count, GLenum type,
|
|
const GLvoid* indices) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawElements(mode, count, type, indices);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fEnable(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnable(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEnableClientState(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnableClientState(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEnableVertexAttribArray(GLuint index) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnableVertexAttribArray(index);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEndQuery(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEndQuery);
|
|
mSymbols.fEndQuery(target);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFinish() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFinish();
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = false;
|
|
}
|
|
|
|
void fFlush() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFlush();
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = false;
|
|
}
|
|
|
|
void fFrontFace(GLenum face) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFrontFace(face);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveAttrib(GLuint program, GLuint index, GLsizei maxLength,
|
|
GLsizei* length, GLint* size, GLenum* type,
|
|
GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveAttrib(program, index, maxLength, length, size, type,
|
|
name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveUniform(GLuint program, GLuint index, GLsizei maxLength,
|
|
GLsizei* length, GLint* size, GLenum* type,
|
|
GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveUniform(program, index, maxLength, length, size, type,
|
|
name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count,
|
|
GLuint* shaders) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLint fGetAttribLocation(GLuint program, const GLchar* name) {
|
|
GLint retval = 0;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fGetAttribLocation(program, name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
private:
|
|
void raw_fGetIntegerv(GLenum pname, GLint* params) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetIntegerv(pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fGetIntegerv(GLenum pname, GLint* params) const;
|
|
|
|
template <typename T>
|
|
void GetInt(const GLenum pname, T* const params) const {
|
|
static_assert(sizeof(T) == sizeof(GLint), "Invalid T.");
|
|
fGetIntegerv(pname, reinterpret_cast<GLint*>(params));
|
|
}
|
|
|
|
void GetUIntegerv(GLenum pname, GLuint* params) const {
|
|
GetInt(pname, params);
|
|
}
|
|
|
|
template <typename T>
|
|
T GetIntAs(GLenum pname) const {
|
|
static_assert(sizeof(T) == sizeof(GLint), "Invalid T.");
|
|
T ret = 0;
|
|
fGetIntegerv(pname, (GLint*)&ret);
|
|
return ret;
|
|
}
|
|
|
|
void fGetFloatv(GLenum pname, GLfloat* params) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetFloatv(pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetBooleanv(GLenum pname, realGLboolean* params) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetBooleanv(pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetBufferParameteriv(target, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLuint fGetDebugMessageLog(GLuint count, GLsizei bufsize, GLenum* sources,
|
|
GLenum* types, GLuint* ids, GLenum* severities,
|
|
GLsizei* lengths, GLchar* messageLog) {
|
|
GLuint ret = 0;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetDebugMessageLog);
|
|
ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids,
|
|
severities, lengths, messageLog);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fGetPointerv(GLenum pname, GLvoid** params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetPointerv);
|
|
mSymbols.fGetPointerv(pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize,
|
|
GLsizei* length, GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetObjectLabel);
|
|
mSymbols.fGetObjectLabel(identifier, name, bufSize, length, label);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetObjectPtrLabel(const GLvoid* ptr, GLsizei bufSize, GLsizei* length,
|
|
GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetObjectPtrLabel);
|
|
mSymbols.fGetObjectPtrLabel(ptr, bufSize, length, label);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGenerateMipmap(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenerateMipmap(target);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetProgramiv(GLuint program, GLenum pname, GLint* param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetProgramiv(program, pname, param);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length,
|
|
GLchar* infoLog) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameteri(target, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameteriv(GLenum target, GLenum pname, const GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameteriv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameterf(target, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
const GLubyte* fGetString(GLenum name) {
|
|
const GLubyte* result = nullptr;
|
|
BEFORE_GL_CALL;
|
|
result = mSymbols.fGetString(name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type,
|
|
GLvoid* img) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTexImage);
|
|
mSymbols.fGetTexImage(target, level, format, type, img);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname,
|
|
GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTexLevelParameteriv);
|
|
mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetTexParameterfv(target, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetTexParameteriv(target, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetUniformfv(GLuint program, GLint location, GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetUniformfv(program, location, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetUniformiv(GLuint program, GLint location, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetUniformiv(program, location, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetUniformuiv(GLuint program, GLint location, GLuint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetUniformuiv);
|
|
mSymbols.fGetUniformuiv(program, location, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLint fGetUniformLocation(GLuint programObj, const GLchar* name) {
|
|
GLint retval = 0;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fGetUniformLocation(programObj, name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribfv(index, pname, retval);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribiv(index, pname, retval);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribPointerv(index, pname, retval);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fHint(GLenum target, GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fHint(target, mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsBuffer(GLuint buffer) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsBuffer(buffer);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsEnabled(GLenum capability) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsEnabled(capability);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void SetEnabled(const GLenum cap, const bool val) {
|
|
if (val) {
|
|
fEnable(cap);
|
|
} else {
|
|
fDisable(cap);
|
|
}
|
|
}
|
|
|
|
bool PushEnabled(const GLenum cap, const bool newVal) {
|
|
const bool oldVal = fIsEnabled(cap);
|
|
if (oldVal != newVal) {
|
|
SetEnabled(cap, newVal);
|
|
}
|
|
return oldVal;
|
|
}
|
|
|
|
realGLboolean fIsProgram(GLuint program) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsProgram(program);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsShader(GLuint shader) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsShader(shader);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsTexture(GLuint texture) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsTexture(texture);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fLineWidth(GLfloat width) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLineWidth(width);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLinkProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLinkProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fObjectLabel(GLenum identifier, GLuint name, GLsizei length,
|
|
const GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fObjectLabel);
|
|
mSymbols.fObjectLabel(identifier, name, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fObjectPtrLabel(const GLvoid* ptr, GLsizei length, const GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fObjectPtrLabel);
|
|
mSymbols.fObjectPtrLabel(ptr, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLoadIdentity() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLoadIdentity();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLoadMatrixf(const GLfloat* matrix) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLoadMatrixf(matrix);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fMatrixMode(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fMatrixMode(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPixelStorei(GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPixelStorei(pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid* pointer) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pointer);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTextureRangeAPPLE(target, length, pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPointParameterf(GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPointParameterf(pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPolygonMode(GLenum face, GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPolygonMode(face, mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPolygonOffset(GLfloat factor, GLfloat bias) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPolygonOffset(factor, bias);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPopDebugGroup() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPopDebugGroup);
|
|
mSymbols.fPopDebugGroup();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPushDebugGroup(GLenum source, GLuint id, GLsizei length,
|
|
const GLchar* message) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPushDebugGroup);
|
|
mSymbols.fPushDebugGroup(source, id, length, message);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fReadBuffer(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fReadBuffer(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
|
GLenum format, GLenum type, GLvoid* pixels) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
|
|
GLenum format, GLenum type, GLvoid* pixels);
|
|
|
|
public:
|
|
void fSampleCoverage(GLclampf value, realGLboolean invert) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fSampleCoverage(value, invert);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
if (mScissorRect[0] == x && mScissorRect[1] == y &&
|
|
mScissorRect[2] == width && mScissorRect[3] == height) {
|
|
return;
|
|
}
|
|
mScissorRect[0] = x;
|
|
mScissorRect[1] = y;
|
|
mScissorRect[2] = width;
|
|
mScissorRect[3] = height;
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fScissor(x, y, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilFunc(GLenum func, GLint reference, GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilFunc(func, reference, mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint reference,
|
|
GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilFuncSeparate(frontfunc, backfunc, reference, mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilMask(GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilMask(mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilMaskSeparate(GLenum face, GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilMaskSeparate(face, mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilOp(fail, zfail, zpass);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail,
|
|
GLenum dppass) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilOpSeparate(face, sfail, dpfail, dppass);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexGeni(GLenum coord, GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexGeni(coord, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexGenf(GLenum coord, GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexGenf(coord, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexGenfv(GLenum coord, GLenum pname, const GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexGenfv(coord, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fTexImage2D(GLenum target, GLint level, GLint internalformat,
|
|
GLsizei width, GLsizei height, GLint border,
|
|
GLenum format, GLenum type, const GLvoid* pixels) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexImage2D(target, level, internalformat, width, height, border,
|
|
format, type, pixels);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
public:
|
|
void fTexImage2D(GLenum target, GLint level, GLint internalformat,
|
|
GLsizei width, GLsizei height, GLint border, GLenum format,
|
|
GLenum type, const GLvoid* pixels);
|
|
|
|
void fTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
|
GLsizei width, GLsizei height, GLenum format, GLenum type,
|
|
const GLvoid* pixels) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexSubImage2D(target, level, xoffset, yoffset, width, height,
|
|
format, type, pixels);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
void fUniform1f(GLint location, GLfloat v0) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform1f(location, v0);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform1fv(GLint location, GLsizei count, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform1fv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform1i(GLint location, GLint v0) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform1i(location, v0);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform1iv(GLint location, GLsizei count, const GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform1iv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2f(GLint location, GLfloat v0, GLfloat v1) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform2f(location, v0, v1);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2fv(GLint location, GLsizei count, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform2fv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2i(GLint location, GLint v0, GLint v1) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform2i(location, v0, v1);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2iv(GLint location, GLsizei count, const GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform2iv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform3f(location, v0, v1, v2);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3fv(GLint location, GLsizei count, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform3fv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform3i(location, v0, v1, v2);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3iv(GLint location, GLsizei count, const GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform3iv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
|
|
GLfloat v3) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform4f(location, v0, v1, v2, v3);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4fv(GLint location, GLsizei count, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform4fv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform4i(location, v0, v1, v2, v3);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4iv(GLint location, GLsizei count, const GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniform4iv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix2fv(GLint location, GLsizei count, realGLboolean transpose,
|
|
const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniformMatrix2fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix2x3fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix2x3fv);
|
|
mSymbols.fUniformMatrix2x3fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix2x4fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix2x4fv);
|
|
mSymbols.fUniformMatrix2x4fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix3fv(GLint location, GLsizei count, realGLboolean transpose,
|
|
const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniformMatrix3fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix3x2fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix3x2fv);
|
|
mSymbols.fUniformMatrix3x2fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix3x4fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix3x4fv);
|
|
mSymbols.fUniformMatrix3x4fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix4fv(GLint location, GLsizei count, realGLboolean transpose,
|
|
const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniformMatrix4fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix4x2fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix4x2fv);
|
|
mSymbols.fUniformMatrix4x2fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformMatrix4x3fv(GLint location, GLsizei count,
|
|
realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniformMatrix4x3fv);
|
|
mSymbols.fUniformMatrix4x3fv(location, count, transpose, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUseProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUseProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fValidateProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fValidateProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribPointer(GLuint index, GLint size, GLenum type,
|
|
realGLboolean normalized, GLsizei stride,
|
|
const GLvoid* pointer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttribPointer(index, size, type, normalized, stride,
|
|
pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib1f(GLuint index, GLfloat x) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib1f(index, x);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib2f(index, x, y);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib3f(index, x, y, z);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z,
|
|
GLfloat w) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib4f(index, x, y, z, w);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib1fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib1fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib2fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib2fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib3fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib3fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib4fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib4fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexPointer(GLint size, GLenum type, GLsizei stride,
|
|
const GLvoid* pointer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexPointer(size, type, stride, pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
if (mViewportRect[0] == x && mViewportRect[1] == y &&
|
|
mViewportRect[2] == width && mViewportRect[3] == height) {
|
|
return;
|
|
}
|
|
mViewportRect[0] = x;
|
|
mViewportRect[1] = y;
|
|
mViewportRect[2] = width;
|
|
mViewportRect[3] = height;
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fViewport(x, y, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fCompileShader(GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCompileShader(shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
friend class SharedSurface_IOSurface;
|
|
|
|
void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
|
|
GLint x, GLint y, GLsizei width, GLsizei height,
|
|
GLint border) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCopyTexImage2D(target, level, internalformat, x, y, width, height,
|
|
border);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset,
|
|
GLint yoffset, GLint x, GLint y, GLsizei width,
|
|
GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width,
|
|
height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fGetShaderiv(GLuint shader, GLenum pname, GLint* param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderiv(shader, pname, param);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length,
|
|
GLchar* infoLog) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
|
|
GLint* range, GLint* precision) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetShaderPrecisionFormat);
|
|
mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range,
|
|
precision);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype,
|
|
GLint* range, GLint* precision) {
|
|
if (IsGLES()) {
|
|
raw_fGetShaderPrecisionFormat(shadertype, precisiontype, range,
|
|
precision);
|
|
} else {
|
|
// Fall back to automatic values because almost all desktop hardware
|
|
// supports the OpenGL standard precisions.
|
|
GetShaderPrecisionFormatNonES2(shadertype, precisiontype, range,
|
|
precision);
|
|
}
|
|
}
|
|
|
|
void fGetShaderSource(GLint obj, GLsizei maxLength, GLsizei* length,
|
|
GLchar* source) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderSource(obj, maxLength, length, source);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fShaderSource(GLuint shader, GLsizei count, const GLchar* const* strings,
|
|
const GLint* lengths) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fShaderSource(shader, count, strings, lengths);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
mutable GLuint mCachedDrawFb = 0;
|
|
mutable GLuint mCachedReadFb = 0;
|
|
|
|
public:
|
|
bool mElideDuplicateBindFramebuffers = false;
|
|
|
|
void fBindFramebuffer(const GLenum target, const GLuint fb) const {
|
|
if (mElideDuplicateBindFramebuffers) {
|
|
MOZ_ASSERT(mCachedDrawFb ==
|
|
GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING));
|
|
MOZ_ASSERT(mCachedReadFb ==
|
|
GetIntAs<GLuint>(LOCAL_GL_READ_FRAMEBUFFER_BINDING));
|
|
|
|
switch (target) {
|
|
case LOCAL_GL_FRAMEBUFFER:
|
|
if (mCachedDrawFb == fb && mCachedReadFb == fb) return;
|
|
break;
|
|
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
|
if (mCachedDrawFb == fb) return;
|
|
break;
|
|
case LOCAL_GL_READ_FRAMEBUFFER:
|
|
if (mCachedReadFb == fb) return;
|
|
break;
|
|
}
|
|
}
|
|
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindFramebuffer(target, fb);
|
|
AFTER_GL_CALL;
|
|
|
|
switch (target) {
|
|
case LOCAL_GL_FRAMEBUFFER:
|
|
mCachedDrawFb = fb;
|
|
mCachedReadFb = fb;
|
|
break;
|
|
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
|
mCachedDrawFb = fb;
|
|
break;
|
|
case LOCAL_GL_READ_FRAMEBUFFER:
|
|
mCachedReadFb = fb;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindRenderbuffer(target, renderbuffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLenum fCheckFramebufferStatus(GLenum target) {
|
|
GLenum retval = 0;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fCheckFramebufferStatus(target);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint,
|
|
GLenum renderbufferTarget,
|
|
GLuint renderbuffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFramebufferRenderbuffer(target, attachmentPoint,
|
|
renderbufferTarget, renderbuffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint,
|
|
GLenum textureTarget, GLuint texture,
|
|
GLint level) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget,
|
|
texture, level);
|
|
AFTER_GL_CALL;
|
|
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);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetRenderbufferParameteriv(target, pname, value);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsFramebuffer(GLuint framebuffer) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsFramebuffer(framebuffer);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
public:
|
|
realGLboolean fIsRenderbuffer(GLuint renderbuffer) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
retval = mSymbols.fIsRenderbuffer(renderbuffer);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width,
|
|
GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fDepthRange(GLclampf a, GLclampf b) {
|
|
MOZ_ASSERT(!IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDepthRange);
|
|
mSymbols.fDepthRange(a, b);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDepthRangef(GLclampf a, GLclampf b) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDepthRangef);
|
|
mSymbols.fDepthRangef(a, b);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fClearDepth(GLclampf v) {
|
|
MOZ_ASSERT(!IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClearDepth);
|
|
mSymbols.fClearDepth(v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fClearDepthf(GLclampf v) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClearDepthf);
|
|
mSymbols.fClearDepthf(v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fDepthRange(GLclampf a, GLclampf b) {
|
|
if (IsGLES()) {
|
|
raw_fDepthRangef(a, b);
|
|
} else {
|
|
raw_fDepthRange(a, b);
|
|
}
|
|
}
|
|
|
|
void fClearDepth(GLclampf v) {
|
|
if (IsGLES()) {
|
|
raw_fClearDepthf(v);
|
|
} else {
|
|
raw_fClearDepth(v);
|
|
}
|
|
}
|
|
|
|
void* fMapBuffer(GLenum target, GLenum access) {
|
|
void* ret = nullptr;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fMapBuffer);
|
|
ret = mSymbols.fMapBuffer(target, access);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
realGLboolean fUnmapBuffer(GLenum target) {
|
|
realGLboolean ret = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
|
|
ret = mSymbols.fUnmapBuffer(target);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
GLuint raw_fCreateProgram() {
|
|
GLuint ret = 0;
|
|
BEFORE_GL_CALL;
|
|
ret = mSymbols.fCreateProgram();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
GLuint raw_fCreateShader(GLenum t) {
|
|
GLuint ret = 0;
|
|
BEFORE_GL_CALL;
|
|
ret = mSymbols.fCreateShader(t);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void raw_fGenBuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenBuffers(n, names);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenFramebuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenFramebuffers(n, names);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenRenderbuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenRenderbuffers(n, names);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenTextures(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenTextures(n, names);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
GLuint fCreateProgram() {
|
|
GLuint ret = raw_fCreateProgram();
|
|
TRACKING_CONTEXT(CreatedProgram(this, ret));
|
|
return ret;
|
|
}
|
|
|
|
GLuint fCreateShader(GLenum t) {
|
|
GLuint ret = raw_fCreateShader(t);
|
|
TRACKING_CONTEXT(CreatedShader(this, ret));
|
|
return ret;
|
|
}
|
|
|
|
void fGenBuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenBuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedBuffers(this, n, names));
|
|
}
|
|
|
|
void fGenFramebuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenFramebuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedFramebuffers(this, n, names));
|
|
}
|
|
|
|
void fGenRenderbuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenRenderbuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedRenderbuffers(this, n, names));
|
|
}
|
|
|
|
void fGenTextures(GLsizei n, GLuint* names) {
|
|
raw_fGenTextures(n, names);
|
|
TRACKING_CONTEXT(CreatedTextures(this, n, names));
|
|
}
|
|
|
|
private:
|
|
void raw_fDeleteProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteShader(GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteShader(shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteBuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteBuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteFramebuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteFramebuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
|
|
for (const auto i : IntegerRange(n)) {
|
|
const auto fb = names[i];
|
|
if (mCachedDrawFb == fb) {
|
|
mCachedDrawFb = 0;
|
|
}
|
|
if (mCachedReadFb == fb) {
|
|
mCachedReadFb = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void raw_fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteRenderbuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteTextures(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteTextures(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fDeleteProgram(GLuint program) {
|
|
raw_fDeleteProgram(program);
|
|
TRACKING_CONTEXT(DeletedProgram(this, program));
|
|
}
|
|
|
|
void fDeleteShader(GLuint shader) {
|
|
raw_fDeleteShader(shader);
|
|
TRACKING_CONTEXT(DeletedShader(this, shader));
|
|
}
|
|
|
|
void fDeleteBuffers(GLsizei n, const GLuint* names) {
|
|
raw_fDeleteBuffers(n, names);
|
|
TRACKING_CONTEXT(DeletedBuffers(this, n, names));
|
|
}
|
|
|
|
void fDeleteFramebuffers(GLsizei n, const GLuint* names);
|
|
|
|
void fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
|
|
raw_fDeleteRenderbuffers(n, names);
|
|
TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
|
|
}
|
|
|
|
void fDeleteTextures(GLsizei n, const GLuint* names) {
|
|
#ifdef XP_MACOSX
|
|
// On the Mac the call to fDeleteTextures() triggers a flush. But it
|
|
// happens at the wrong time, which can lead to crashes. To work around
|
|
// this we call fFlush() explicitly ourselves, before the call to
|
|
// fDeleteTextures(). This fixes bug 1666293.
|
|
fFlush();
|
|
#endif
|
|
raw_fDeleteTextures(n, names);
|
|
TRACKING_CONTEXT(DeletedTextures(this, n, names));
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension ARB_sync (GL)
|
|
public:
|
|
GLsync fFenceSync(GLenum condition, GLbitfield flags) {
|
|
GLsync ret = 0;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fFenceSync);
|
|
ret = mSymbols.fFenceSync(condition, flags);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
realGLboolean fIsSync(GLsync sync) {
|
|
realGLboolean ret = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsSync);
|
|
ret = mSymbols.fIsSync(sync);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fDeleteSync(GLsync sync) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteSync);
|
|
mSymbols.fDeleteSync(sync);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLenum fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
|
GLenum ret = 0;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClientWaitSync);
|
|
ret = mSymbols.fClientWaitSync(sync, flags, timeout);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fWaitSync);
|
|
mSymbols.fWaitSync(sync, flags, timeout);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetInteger64v(GLenum pname, GLint64* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetInteger64v);
|
|
mSymbols.fGetInteger64v(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length,
|
|
GLint* values) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetSynciv);
|
|
mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension OES_EGL_image (GLES)
|
|
public:
|
|
void fEGLImageTargetTexture2D(GLenum target, GLeglImage image) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEGLImageTargetTexture2D);
|
|
mSymbols.fEGLImageTargetTexture2D(target, image);
|
|
AFTER_GL_CALL;
|
|
mHeavyGLCallsSinceLastFlush = true;
|
|
}
|
|
|
|
void fEGLImageTargetRenderbufferStorage(GLenum target, GLeglImage image) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEGLImageTargetRenderbufferStorage);
|
|
mSymbols.fEGLImageTargetRenderbufferStorage(target, image);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_bind_buffer_offset
|
|
public:
|
|
void fBindBufferOffset(GLenum target, GLuint index, GLuint buffer,
|
|
GLintptr offset) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindBufferOffset);
|
|
mSymbols.fBindBufferOffset(target, index, buffer, offset);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_draw_buffers
|
|
public:
|
|
void fDrawBuffers(GLsizei n, const GLenum* bufs) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawBuffers);
|
|
mSymbols.fDrawBuffers(n, bufs);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_draw_instanced
|
|
public:
|
|
void fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
|
|
GLsizei primcount) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawArraysInstanced(mode, first, count, primcount);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
|
const GLvoid* indices, GLsizei primcount) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawElementsInstanced(mode, count, type, indices, primcount);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
private:
|
|
void raw_fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count,
|
|
GLsizei primcount) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawArraysInstanced);
|
|
mSymbols.fDrawArraysInstanced(mode, first, count, primcount);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
|
|
const GLvoid* indices, GLsizei primcount) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawElementsInstanced);
|
|
mSymbols.fDrawElementsInstanced(mode, count, type, indices, primcount);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_framebuffer_blit
|
|
public:
|
|
// Draw/Read
|
|
void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
|
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
|
GLbitfield mask, GLenum filter) {
|
|
BeforeGLDrawCall();
|
|
BeforeGLReadCall();
|
|
raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
|
|
mask, filter);
|
|
AfterGLReadCall();
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
private:
|
|
void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
|
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
|
GLbitfield mask, GLenum filter) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBlitFramebuffer);
|
|
mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
|
|
dstY1, mask, filter);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_framebuffer_multisample
|
|
public:
|
|
void fRenderbufferStorageMultisample(GLenum target, GLsizei samples,
|
|
GLenum internalFormat, GLsizei width,
|
|
GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fRenderbufferStorageMultisample);
|
|
mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat,
|
|
width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// GL 3.0, GL ES 3.0 & EXT_gpu_shader4
|
|
public:
|
|
void fGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) {
|
|
ASSERT_SYMBOL_PRESENT(fGetVertexAttribIiv);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribIiv(index, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) {
|
|
ASSERT_SYMBOL_PRESENT(fGetVertexAttribIuiv);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribIuiv(index, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribI4i);
|
|
mSymbols.fVertexAttribI4i(index, x, y, z, w);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribI4iv(GLuint index, const GLint* v) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribI4iv);
|
|
mSymbols.fVertexAttribI4iv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribI4ui);
|
|
mSymbols.fVertexAttribI4ui(index, x, y, z, w);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribI4uiv(GLuint index, const GLuint* v) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribI4uiv);
|
|
mSymbols.fVertexAttribI4uiv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribIPointer(GLuint index, GLint size, GLenum type,
|
|
GLsizei stride, const GLvoid* offset) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribIPointer);
|
|
mSymbols.fVertexAttribIPointer(index, size, type, stride, offset);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform1ui(GLint location, GLuint v0) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform1ui);
|
|
mSymbols.fUniform1ui(location, v0);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2ui(GLint location, GLuint v0, GLuint v1) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform2ui);
|
|
mSymbols.fUniform2ui(location, v0, v1);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform3ui);
|
|
mSymbols.fUniform3ui(location, v0, v1, v2);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform4ui);
|
|
mSymbols.fUniform4ui(location, v0, v1, v2, v3);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform1uiv(GLint location, GLsizei count, const GLuint* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform1uiv);
|
|
mSymbols.fUniform1uiv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform2uiv(GLint location, GLsizei count, const GLuint* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform2uiv);
|
|
mSymbols.fUniform2uiv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform3uiv(GLint location, GLsizei count, const GLuint* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform3uiv);
|
|
mSymbols.fUniform3uiv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniform4uiv(GLint location, GLsizei count, const GLuint* value) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUniform4uiv);
|
|
mSymbols.fUniform4uiv(location, count, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLint fGetFragDataLocation(GLuint program, const GLchar* name) {
|
|
GLint result = 0;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetFragDataLocation);
|
|
result = mSymbols.fGetFragDataLocation(program, name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_instanced_arrays
|
|
public:
|
|
void fVertexAttribDivisor(GLuint index, GLuint divisor) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fVertexAttribDivisor);
|
|
mSymbols.fVertexAttribDivisor(index, divisor);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Feature internalformat_query
|
|
public:
|
|
void fGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname,
|
|
GLsizei bufSize, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetInternalformativ);
|
|
mSymbols.fGetInternalformativ(target, internalformat, pname, bufSize,
|
|
params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_query_counter
|
|
/**
|
|
* XXX_query_counter:
|
|
* - depends on XXX_query_objects
|
|
* - provide all followed entry points
|
|
* - provide GL_TIMESTAMP
|
|
*/
|
|
public:
|
|
void fQueryCounter(GLuint id, GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fQueryCounter);
|
|
mSymbols.fQueryCounter(id, target);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_query_objects
|
|
/**
|
|
* XXX_query_objects:
|
|
* - provide all followed entry points
|
|
*
|
|
* XXX_occlusion_query2:
|
|
* - depends on XXX_query_objects
|
|
* - provide ANY_SAMPLES_PASSED
|
|
*
|
|
* XXX_occlusion_query_boolean:
|
|
* - depends on XXX_occlusion_query2
|
|
* - provide ANY_SAMPLES_PASSED_CONSERVATIVE
|
|
*/
|
|
public:
|
|
void fDeleteQueries(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteQueries);
|
|
mSymbols.fDeleteQueries(n, names);
|
|
AFTER_GL_CALL;
|
|
TRACKING_CONTEXT(DeletedQueries(this, n, names));
|
|
}
|
|
|
|
void fGenQueries(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenQueries);
|
|
mSymbols.fGenQueries(n, names);
|
|
AFTER_GL_CALL;
|
|
TRACKING_CONTEXT(CreatedQueries(this, n, names));
|
|
}
|
|
|
|
void fGetQueryiv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryiv);
|
|
mSymbols.fGetQueryiv(target, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjectuiv);
|
|
mSymbols.fGetQueryObjectuiv(id, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsQuery(GLuint query) {
|
|
realGLboolean retval = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsQuery);
|
|
retval = mSymbols.fIsQuery(query);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_get_query_object_i64v
|
|
/**
|
|
* XXX_get_query_object_i64v:
|
|
* - depends on XXX_query_objects
|
|
* - provide the followed entry point
|
|
*/
|
|
public:
|
|
void fGetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjecti64v);
|
|
mSymbols.fGetQueryObjecti64v(id, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjectui64v);
|
|
mSymbols.fGetQueryObjectui64v(id, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_get_query_object_iv
|
|
/**
|
|
* XXX_get_query_object_iv:
|
|
* - depends on XXX_query_objects
|
|
* - provide the followed entry point
|
|
*
|
|
* XXX_occlusion_query:
|
|
* - depends on XXX_get_query_object_iv
|
|
* - provide LOCAL_GL_SAMPLES_PASSED
|
|
*/
|
|
public:
|
|
void fGetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjectiv);
|
|
mSymbols.fGetQueryObjectiv(id, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// GL 4.0, GL ES 3.0, ARB_transform_feedback2, NV_transform_feedback2
|
|
public:
|
|
void fBindBufferBase(GLenum target, GLuint index, GLuint buffer) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindBufferBase);
|
|
mSymbols.fBindBufferBase(target, index, buffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindBufferRange(GLenum target, GLuint index, GLuint buffer,
|
|
GLintptr offset, GLsizeiptr size) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindBufferRange);
|
|
mSymbols.fBindBufferRange(target, index, buffer, offset, size);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGenTransformFeedbacks(GLsizei n, GLuint* ids) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenTransformFeedbacks);
|
|
mSymbols.fGenTransformFeedbacks(n, ids);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDeleteTransformFeedbacks(GLsizei n, const GLuint* ids) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteTransformFeedbacks);
|
|
mSymbols.fDeleteTransformFeedbacks(n, ids);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsTransformFeedback(GLuint id) {
|
|
realGLboolean result = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsTransformFeedback);
|
|
result = mSymbols.fIsTransformFeedback(id);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
void fBindTransformFeedback(GLenum target, GLuint id) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindTransformFeedback);
|
|
mSymbols.fBindTransformFeedback(target, id);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBeginTransformFeedback(GLenum primitiveMode) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBeginTransformFeedback);
|
|
mSymbols.fBeginTransformFeedback(primitiveMode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEndTransformFeedback() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEndTransformFeedback);
|
|
mSymbols.fEndTransformFeedback();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTransformFeedbackVaryings(GLuint program, GLsizei count,
|
|
const GLchar* const* varyings,
|
|
GLenum bufferMode) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTransformFeedbackVaryings);
|
|
mSymbols.fTransformFeedbackVaryings(program, count, varyings, bufferMode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTransformFeedbackVarying(GLuint program, GLuint index,
|
|
GLsizei bufSize, GLsizei* length,
|
|
GLsizei* size, GLenum* type, GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTransformFeedbackVarying);
|
|
mSymbols.fGetTransformFeedbackVarying(program, index, bufSize, length, size,
|
|
type, name);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPauseTransformFeedback() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPauseTransformFeedback);
|
|
mSymbols.fPauseTransformFeedback();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fResumeTransformFeedback() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fResumeTransformFeedback);
|
|
mSymbols.fResumeTransformFeedback();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetIntegeri_v(GLenum param, GLuint index, GLint* values) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetIntegeri_v);
|
|
mSymbols.fGetIntegeri_v(param, index, values);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetInteger64i_v(GLenum target, GLuint index, GLint64* data) {
|
|
ASSERT_SYMBOL_PRESENT(fGetInteger64i_v);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetInteger64i_v(target, index, data);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_vertex_array_object
|
|
public:
|
|
void fBindVertexArray(GLuint array) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindVertexArray);
|
|
mSymbols.fBindVertexArray(array);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDeleteVertexArrays(GLsizei n, const GLuint* arrays) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteVertexArrays);
|
|
mSymbols.fDeleteVertexArrays(n, arrays);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGenVertexArrays(GLsizei n, GLuint* arrays) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenVertexArrays);
|
|
mSymbols.fGenVertexArrays(n, arrays);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsVertexArray(GLuint array) {
|
|
realGLboolean ret = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsVertexArray);
|
|
ret = mSymbols.fIsVertexArray(array);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension NV_fence
|
|
public:
|
|
void fGenFences(GLsizei n, GLuint* fences) {
|
|
ASSERT_SYMBOL_PRESENT(fGenFences);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenFences(n, fences);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDeleteFences(GLsizei n, const GLuint* fences) {
|
|
ASSERT_SYMBOL_PRESENT(fDeleteFences);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteFences(n, fences);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fSetFence(GLuint fence, GLenum condition) {
|
|
ASSERT_SYMBOL_PRESENT(fSetFence);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fSetFence(fence, condition);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fTestFence(GLuint fence) {
|
|
realGLboolean ret = false;
|
|
ASSERT_SYMBOL_PRESENT(fTestFence);
|
|
BEFORE_GL_CALL;
|
|
ret = mSymbols.fTestFence(fence);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fFinishFence(GLuint fence) {
|
|
ASSERT_SYMBOL_PRESENT(fFinishFence);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFinishFence(fence);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsFence(GLuint fence) {
|
|
realGLboolean ret = false;
|
|
ASSERT_SYMBOL_PRESENT(fIsFence);
|
|
BEFORE_GL_CALL;
|
|
ret = mSymbols.fIsFence(fence);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fGetFenceiv(GLuint fence, GLenum pname, GLint* params) {
|
|
ASSERT_SYMBOL_PRESENT(fGetFenceiv);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetFenceiv(fence, pname, params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension NV_texture_barrier
|
|
public:
|
|
void fTextureBarrier() {
|
|
ASSERT_SYMBOL_PRESENT(fTextureBarrier);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTextureBarrier();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// Core GL & Extension ARB_copy_buffer
|
|
public:
|
|
void fCopyBufferSubData(GLenum readtarget, GLenum writetarget,
|
|
GLintptr readoffset, GLintptr writeoffset,
|
|
GLsizeiptr size) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fCopyBufferSubData);
|
|
mSymbols.fCopyBufferSubData(readtarget, writetarget, readoffset,
|
|
writeoffset, size);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Core GL & Extension ARB_map_buffer_range
|
|
public:
|
|
void* fMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
|
|
GLbitfield access) {
|
|
void* data = nullptr;
|
|
ASSERT_SYMBOL_PRESENT(fMapBufferRange);
|
|
BEFORE_GL_CALL;
|
|
data = mSymbols.fMapBufferRange(target, offset, length, access);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return data;
|
|
}
|
|
|
|
void fFlushMappedBufferRange(GLenum target, GLintptr offset,
|
|
GLsizeiptr length) {
|
|
ASSERT_SYMBOL_PRESENT(fFlushMappedBufferRange);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFlushMappedBufferRange(target, offset, length);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Core GL & Extension ARB_sampler_objects
|
|
public:
|
|
void fGenSamplers(GLsizei count, GLuint* samplers) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenSamplers);
|
|
mSymbols.fGenSamplers(count, samplers);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDeleteSamplers(GLsizei count, const GLuint* samplers) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteSamplers);
|
|
mSymbols.fDeleteSamplers(count, samplers);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsSampler(GLuint sampler) {
|
|
realGLboolean result = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsSampler);
|
|
result = mSymbols.fIsSampler(sampler);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
void fBindSampler(GLuint unit, GLuint sampler) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindSampler);
|
|
mSymbols.fBindSampler(unit, sampler);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fSamplerParameteri(GLuint sampler, GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fSamplerParameteri);
|
|
mSymbols.fSamplerParameteri(sampler, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fSamplerParameteriv);
|
|
mSymbols.fSamplerParameteriv(sampler, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fSamplerParameterf);
|
|
mSymbols.fSamplerParameterf(sampler, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fSamplerParameterfv);
|
|
mSymbols.fSamplerParameterfv(sampler, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetSamplerParameteriv);
|
|
mSymbols.fGetSamplerParameteriv(sampler, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetSamplerParameterfv);
|
|
mSymbols.fGetSamplerParameterfv(sampler, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Core GL & Extension ARB_uniform_buffer_object
|
|
public:
|
|
void fGetUniformIndices(GLuint program, GLsizei uniformCount,
|
|
const GLchar* const* uniformNames,
|
|
GLuint* uniformIndices) {
|
|
ASSERT_SYMBOL_PRESENT(fGetUniformIndices);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetUniformIndices(program, uniformCount, uniformNames,
|
|
uniformIndices);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveUniformsiv(GLuint program, GLsizei uniformCount,
|
|
const GLuint* uniformIndices, GLenum pname,
|
|
GLint* params) {
|
|
ASSERT_SYMBOL_PRESENT(fGetActiveUniformsiv);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveUniformsiv(program, uniformCount, uniformIndices, pname,
|
|
params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLuint fGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) {
|
|
GLuint result = 0;
|
|
ASSERT_SYMBOL_PRESENT(fGetUniformBlockIndex);
|
|
BEFORE_GL_CALL;
|
|
result = mSymbols.fGetUniformBlockIndex(program, uniformBlockName);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
void fGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex,
|
|
GLenum pname, GLint* params) {
|
|
ASSERT_SYMBOL_PRESENT(fGetActiveUniformBlockiv);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveUniformBlockiv(program, uniformBlockIndex, pname,
|
|
params);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex,
|
|
GLsizei bufSize, GLsizei* length,
|
|
GLchar* uniformBlockName) {
|
|
ASSERT_SYMBOL_PRESENT(fGetActiveUniformBlockName);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveUniformBlockName(program, uniformBlockIndex, bufSize,
|
|
length, uniformBlockName);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fUniformBlockBinding(GLuint program, GLuint uniformBlockIndex,
|
|
GLuint uniformBlockBinding) {
|
|
ASSERT_SYMBOL_PRESENT(fUniformBlockBinding);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniformBlockBinding(program, uniformBlockIndex,
|
|
uniformBlockBinding);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Core GL 4.2, GL ES 3.0 & Extension ARB_texture_storage/EXT_texture_storage
|
|
void fTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
|
|
GLsizei width, GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTexStorage2D);
|
|
mSymbols.fTexStorage2D(target, levels, internalformat, width, height);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
|
|
GLsizei width, GLsizei height, GLsizei depth) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTexStorage3D);
|
|
mSymbols.fTexStorage3D(target, levels, internalformat, width, height,
|
|
depth);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// 3D Textures
|
|
void fTexImage3D(GLenum target, GLint level, GLint internalFormat,
|
|
GLsizei width, GLsizei height, GLsizei depth, GLint border,
|
|
GLenum format, GLenum type, const GLvoid* data) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTexImage3D);
|
|
mSymbols.fTexImage3D(target, level, internalFormat, width, height, depth,
|
|
border, format, type, data);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
|
GLint zoffset, GLsizei width, GLsizei height,
|
|
GLsizei depth, GLenum format, GLenum type,
|
|
const GLvoid* pixels) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTexSubImage3D);
|
|
mSymbols.fTexSubImage3D(target, level, xoffset, yoffset, zoffset, width,
|
|
height, depth, format, type, pixels);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset,
|
|
GLint yoffset, GLint zoffset, GLint x, GLint y,
|
|
GLsizei width, GLsizei height) {
|
|
BeforeGLReadCall();
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fCopyTexSubImage3D);
|
|
mSymbols.fCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y,
|
|
width, height);
|
|
AFTER_GL_CALL;
|
|
AfterGLReadCall();
|
|
}
|
|
|
|
void fCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
|
|
GLsizei width, GLsizei height, GLsizei depth,
|
|
GLint border, GLsizei imageSize,
|
|
const GLvoid* data) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fCompressedTexImage3D);
|
|
mSymbols.fCompressedTexImage3D(target, level, internalformat, width, height,
|
|
depth, border, imageSize, data);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
|
|
GLint yoffset, GLint zoffset, GLsizei width,
|
|
GLsizei height, GLsizei depth, GLenum format,
|
|
GLsizei imageSize, const GLvoid* data) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fCompressedTexSubImage3D);
|
|
mSymbols.fCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset,
|
|
width, height, depth, format, imageSize,
|
|
data);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// GL3+, ES3+
|
|
|
|
const GLubyte* fGetStringi(GLenum name, GLuint index) {
|
|
const GLubyte* ret = nullptr;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetStringi);
|
|
ret = mSymbols.fGetStringi(name, index);
|
|
OnSyncCall();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// APPLE_framebuffer_multisample
|
|
|
|
void fResolveMultisampleFramebufferAPPLE() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fResolveMultisampleFramebufferAPPLE);
|
|
mSymbols.fResolveMultisampleFramebufferAPPLE();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// APPLE_fence
|
|
|
|
void fFinishObjectAPPLE(GLenum object, GLint name) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fFinishObjectAPPLE);
|
|
mSymbols.fFinishObjectAPPLE(object, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fTestObjectAPPLE(GLenum object, GLint name) {
|
|
realGLboolean ret = false;
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTestObjectAPPLE);
|
|
ret = mSymbols.fTestObjectAPPLE(object, name);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// prim_restart
|
|
|
|
void fPrimitiveRestartIndex(GLuint index) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPrimitiveRestartIndex);
|
|
mSymbols.fPrimitiveRestartIndex(index);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// multiview
|
|
|
|
void fFramebufferTextureMultiview(GLenum target, GLenum attachment,
|
|
GLuint texture, GLint level,
|
|
GLint baseViewIndex,
|
|
GLsizei numViews) const {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fFramebufferTextureMultiview);
|
|
mSymbols.fFramebufferTextureMultiview(target, attachment, texture, level,
|
|
baseViewIndex, numViews);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -
|
|
// draw_buffers_indexed
|
|
|
|
void fBlendEquationSeparatei(GLuint i, GLenum modeRGB,
|
|
GLenum modeAlpha) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendEquationSeparatei(i, modeRGB, modeAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendFuncSeparatei(GLuint i, GLenum sfactorRGB, GLenum dfactorRGB,
|
|
GLenum sfactorAlpha, GLenum dfactorAlpha) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendFuncSeparatei(i, sfactorRGB, dfactorRGB, sfactorAlpha,
|
|
dfactorAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fColorMaski(GLuint i, realGLboolean red, realGLboolean green,
|
|
realGLboolean blue, realGLboolean alpha) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fColorMaski(i, red, green, blue, alpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisablei(GLenum capability, GLuint i) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisablei(capability, i);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEnablei(GLenum capability, GLuint i) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnablei(capability, i);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -
|
|
|
|
void fProvokingVertex(GLenum mode) const {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fProvokingVertex(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -
|
|
|
|
#undef BEFORE_GL_CALL
|
|
#undef AFTER_GL_CALL
|
|
#undef ASSERT_SYMBOL_PRESENT
|
|
// #undef TRACKING_CONTEXT // Needed in GLContext.cpp
|
|
#undef ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Constructor
|
|
protected:
|
|
explicit GLContext(const GLContextDesc&, GLContext* sharedContext = nullptr,
|
|
bool canUseTLSIsCurrent = false);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Destructor
|
|
public:
|
|
virtual ~GLContext();
|
|
|
|
// Mark this context as destroyed. This will nullptr out all
|
|
// the GL function pointers!
|
|
void MarkDestroyed();
|
|
|
|
protected:
|
|
virtual void OnMarkDestroyed() {}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Everything that isn't standard GL APIs
|
|
protected:
|
|
typedef gfx::SurfaceFormat SurfaceFormat;
|
|
|
|
public:
|
|
virtual void ReleaseSurface() {}
|
|
|
|
bool IsDestroyed() const {
|
|
// MarkDestroyed will mark all these as null.
|
|
return mContextLost && mSymbols.fUseProgram == nullptr;
|
|
}
|
|
|
|
GLContext* GetSharedContext() { return mSharedContext; }
|
|
|
|
/**
|
|
* Returns true if the thread on which this context was created is the
|
|
* currently executing thread.
|
|
*/
|
|
bool IsValidOwningThread() const;
|
|
|
|
static void PlatformStartup();
|
|
|
|
public:
|
|
/**
|
|
* If this context wraps a double-buffered target, swap the back
|
|
* and front buffers. It should be assumed that after a swap, the
|
|
* contents of the new back buffer are undefined.
|
|
*/
|
|
virtual bool SwapBuffers() { return false; }
|
|
|
|
/**
|
|
* Stores a damage region (in origin bottom left coordinates), which
|
|
* makes the next SwapBuffers call do eglSwapBuffersWithDamage if supported.
|
|
*
|
|
* Note that even if only part of the context is damaged, the entire buffer
|
|
* needs to be filled with up-to-date contents. This region is only a hint
|
|
* telling the system compositor which parts of the buffer were updated.
|
|
*/
|
|
virtual void SetDamage(const nsIntRegion& aDamageRegion) {}
|
|
|
|
/**
|
|
* Get the buffer age. If it returns 0, that indicates the buffer state is
|
|
* unknown and the entire frame should be redrawn.
|
|
*/
|
|
virtual GLint GetBufferAge() const { return 0; }
|
|
|
|
/**
|
|
* Defines a two-dimensional texture image for context target surface
|
|
*/
|
|
virtual bool BindTexImage() { return false; }
|
|
/*
|
|
* Releases a color buffer that is being used as a texture
|
|
*/
|
|
virtual bool ReleaseTexImage() { return false; }
|
|
|
|
virtual Maybe<SymbolLoader> GetSymbolLoader() const = 0;
|
|
|
|
void BindFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
|
|
MOZ_GL_ASSERT(this, !fb || fIsFramebuffer(fb));
|
|
}
|
|
|
|
void BindDrawFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb);
|
|
}
|
|
|
|
void BindReadFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, fb);
|
|
}
|
|
|
|
GLuint GetDrawFB() const {
|
|
return GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT);
|
|
}
|
|
|
|
GLuint GetReadFB() const {
|
|
auto bindEnum = LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT;
|
|
if (!IsSupported(GLFeature::split_framebuffer)) {
|
|
bindEnum = LOCAL_GL_FRAMEBUFFER_BINDING;
|
|
}
|
|
return GetIntAs<GLuint>(bindEnum);
|
|
}
|
|
|
|
GLuint GetFB() const {
|
|
const auto ret = GetDrawFB();
|
|
MOZ_ASSERT(ret == GetReadFB());
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype,
|
|
GLint* range, GLint* precision) {
|
|
switch (precisiontype) {
|
|
case LOCAL_GL_LOW_FLOAT:
|
|
case LOCAL_GL_MEDIUM_FLOAT:
|
|
case LOCAL_GL_HIGH_FLOAT:
|
|
// Assume IEEE 754 precision
|
|
range[0] = 127;
|
|
range[1] = 127;
|
|
*precision = 23;
|
|
break;
|
|
case LOCAL_GL_LOW_INT:
|
|
case LOCAL_GL_MEDIUM_INT:
|
|
case LOCAL_GL_HIGH_INT:
|
|
// Some (most) hardware only supports single-precision floating-point
|
|
// numbers, which can accurately represent integers up to +/-16777216
|
|
range[0] = 24;
|
|
range[1] = 24;
|
|
*precision = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public:
|
|
virtual GLenum GetPreferredARGB32Format() const { return LOCAL_GL_RGBA; }
|
|
|
|
virtual GLenum GetPreferredEGLImageTextureTarget() const {
|
|
#ifdef MOZ_WIDGET_GTK
|
|
return LOCAL_GL_TEXTURE_2D;
|
|
#else
|
|
return IsExtensionSupported(OES_EGL_image_external)
|
|
? LOCAL_GL_TEXTURE_EXTERNAL
|
|
: LOCAL_GL_TEXTURE_2D;
|
|
#endif
|
|
}
|
|
|
|
virtual bool RenewSurface(widget::CompositorWidget* aWidget) { return false; }
|
|
|
|
// Shared code for GL extensions and GLX extensions.
|
|
static bool ListHasExtension(const GLubyte* extensions,
|
|
const char* extension);
|
|
|
|
public:
|
|
enum {
|
|
DebugFlagEnabled = 1 << 0,
|
|
DebugFlagTrace = 1 << 1,
|
|
DebugFlagAbortOnError = 1 << 2
|
|
};
|
|
|
|
const uint8_t mDebugFlags;
|
|
static uint8_t ChooseDebugFlags(CreateContextFlags createFlags);
|
|
|
|
protected:
|
|
RefPtr<GLContext> mSharedContext;
|
|
|
|
public:
|
|
// The thread id which this context was created.
|
|
Maybe<PlatformThreadId> mOwningThreadId;
|
|
|
|
protected:
|
|
GLContextSymbols mSymbols = {};
|
|
|
|
UniquePtr<GLBlitHelper> mBlitHelper;
|
|
UniquePtr<GLReadTexImageHelper> mReadTexImageHelper;
|
|
|
|
public:
|
|
GLBlitHelper* BlitHelper();
|
|
GLReadTexImageHelper* ReadTexImageHelper();
|
|
|
|
// Assumes shares are created by all sharing with the same global context.
|
|
bool SharesWith(const GLContext* other) const {
|
|
MOZ_ASSERT(!this->mSharedContext || !this->mSharedContext->mSharedContext);
|
|
MOZ_ASSERT(!other->mSharedContext ||
|
|
!other->mSharedContext->mSharedContext);
|
|
MOZ_ASSERT(!this->mSharedContext || !other->mSharedContext ||
|
|
this->mSharedContext == other->mSharedContext);
|
|
|
|
const GLContext* thisShared =
|
|
this->mSharedContext ? this->mSharedContext : this;
|
|
const GLContext* otherShared =
|
|
other->mSharedContext ? other->mSharedContext : other;
|
|
|
|
return thisShared == otherShared;
|
|
}
|
|
|
|
bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
|
|
|
|
// Does not check completeness.
|
|
void AttachBuffersToFB(GLuint colorTex, GLuint colorRB, GLuint depthRB,
|
|
GLuint stencilRB, GLuint fb,
|
|
GLenum target = LOCAL_GL_TEXTURE_2D);
|
|
|
|
// Passing null is fine if the value you'd get is 0.
|
|
bool AssembleOffscreenFBs(const GLuint colorMSRB, const GLuint depthRB,
|
|
const GLuint stencilRB, const GLuint texture,
|
|
GLuint* drawFB, GLuint* readFB);
|
|
|
|
protected:
|
|
SharedSurface* mLockedSurface = nullptr;
|
|
|
|
public:
|
|
void LockSurface(SharedSurface* surf) { mLockedSurface = surf; }
|
|
|
|
void UnlockSurface(SharedSurface* surf) {
|
|
MOZ_ASSERT(mLockedSurface == surf);
|
|
mLockedSurface = nullptr;
|
|
}
|
|
|
|
SharedSurface* GetLockedSurface() const { return mLockedSurface; }
|
|
|
|
bool IsOffscreen() const { return mDesc.isOffscreen; }
|
|
|
|
bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
|
|
|
|
bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const;
|
|
|
|
virtual bool Init();
|
|
|
|
private:
|
|
bool InitImpl();
|
|
void LoadMoreSymbols(const SymbolLoader& loader);
|
|
bool LoadExtSymbols(const SymbolLoader& loader, const SymLoadStruct* list,
|
|
GLExtensions ext);
|
|
bool LoadFeatureSymbols(const SymbolLoader& loader, const SymLoadStruct* list,
|
|
GLFeature feature);
|
|
|
|
protected:
|
|
void InitExtensions();
|
|
|
|
GLint mViewportRect[4] = {};
|
|
GLint mScissorRect[4] = {};
|
|
|
|
uint32_t mMaxTexOrRbSize = 0;
|
|
GLint mMaxTextureSize = 0;
|
|
GLint mMaxCubeMapTextureSize = 0;
|
|
GLint mMaxRenderbufferSize = 0;
|
|
GLint mMaxViewportDims[2] = {};
|
|
GLsizei mMaxSamples = 0;
|
|
bool mNeedsTextureSizeChecks = false;
|
|
bool mNeedsFlushBeforeDeleteFB = false;
|
|
bool mTextureAllocCrashesOnMapFailure = false;
|
|
bool mNeedsCheckAfterAttachTextureToFb = false;
|
|
const bool mWorkAroundDriverBugs;
|
|
mutable uint64_t mSyncGLCallCount = 0;
|
|
|
|
bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width,
|
|
GLsizei height) const {
|
|
if (mNeedsTextureSizeChecks) {
|
|
// some drivers incorrectly handle some large texture sizes that are below
|
|
// the max texture size that they report. So we check ourselves against
|
|
// our own values (mMax[CubeMap]TextureSize). see bug 737182 for Mac Intel
|
|
// 2D textures see bug 684882 for Mac Intel cube map textures see bug
|
|
// 814716 for Mesa Nouveau
|
|
GLsizei maxSize =
|
|
target == LOCAL_GL_TEXTURE_CUBE_MAP ||
|
|
(target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
|
|
target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
|
|
? mMaxCubeMapTextureSize
|
|
: mMaxTextureSize;
|
|
return width <= maxSize && height <= maxSize;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public:
|
|
auto MaxSamples() const { return uint32_t(mMaxSamples); }
|
|
auto MaxTextureSize() const { return uint32_t(mMaxTextureSize); }
|
|
auto MaxRenderbufferSize() const { return uint32_t(mMaxRenderbufferSize); }
|
|
auto MaxTexOrRbSize() const { return mMaxTexOrRbSize; }
|
|
|
|
#ifdef MOZ_GL_DEBUG_BUILD
|
|
void CreatedProgram(GLContext* aOrigin, GLuint aName);
|
|
void CreatedShader(GLContext* aOrigin, GLuint aName);
|
|
void CreatedBuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
|
|
void CreatedQueries(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
|
|
void CreatedTextures(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
|
|
void CreatedFramebuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
|
|
void CreatedRenderbuffers(GLContext* aOrigin, GLsizei aCount, GLuint* aNames);
|
|
void DeletedProgram(GLContext* aOrigin, GLuint aName);
|
|
void DeletedShader(GLContext* aOrigin, GLuint aName);
|
|
void DeletedBuffers(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames);
|
|
void DeletedQueries(GLContext* aOrigin, GLsizei aCount, const GLuint* aNames);
|
|
void DeletedTextures(GLContext* aOrigin, GLsizei aCount,
|
|
const GLuint* aNames);
|
|
void DeletedFramebuffers(GLContext* aOrigin, GLsizei aCount,
|
|
const GLuint* aNames);
|
|
void DeletedRenderbuffers(GLContext* aOrigin, GLsizei aCount,
|
|
const GLuint* aNames);
|
|
|
|
void SharedContextDestroyed(GLContext* aChild);
|
|
void ReportOutstandingNames();
|
|
|
|
struct NamedResource {
|
|
NamedResource() : origin(nullptr), name(0), originDeleted(false) {}
|
|
|
|
NamedResource(GLContext* aOrigin, GLuint aName)
|
|
: origin(aOrigin), name(aName), originDeleted(false) {}
|
|
|
|
GLContext* origin;
|
|
GLuint name;
|
|
bool originDeleted;
|
|
|
|
// for sorting
|
|
bool operator<(const NamedResource& aOther) const {
|
|
if (intptr_t(origin) < intptr_t(aOther.origin)) return true;
|
|
if (name < aOther.name) return true;
|
|
return false;
|
|
}
|
|
bool operator==(const NamedResource& aOther) const {
|
|
return origin == aOther.origin && name == aOther.name &&
|
|
originDeleted == aOther.originDeleted;
|
|
}
|
|
};
|
|
|
|
nsTArray<NamedResource> mTrackedPrograms;
|
|
nsTArray<NamedResource> mTrackedShaders;
|
|
nsTArray<NamedResource> mTrackedTextures;
|
|
nsTArray<NamedResource> mTrackedFramebuffers;
|
|
nsTArray<NamedResource> mTrackedRenderbuffers;
|
|
nsTArray<NamedResource> mTrackedBuffers;
|
|
nsTArray<NamedResource> mTrackedQueries;
|
|
#endif
|
|
|
|
protected:
|
|
bool mHeavyGLCallsSinceLastFlush = false;
|
|
|
|
public:
|
|
void FlushIfHeavyGLCallsSinceLastFlush();
|
|
static bool ShouldSpew();
|
|
static bool ShouldDumpExts();
|
|
|
|
// --
|
|
|
|
void TexParams_SetClampNoMips(GLenum target = LOCAL_GL_TEXTURE_2D) {
|
|
fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
|
|
fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
|
|
fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
|
|
fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
|
|
}
|
|
|
|
// --
|
|
|
|
GLuint CreateFramebuffer() {
|
|
GLuint x = 0;
|
|
fGenFramebuffers(1, &x);
|
|
return x;
|
|
}
|
|
GLuint CreateRenderbuffer() {
|
|
GLuint x = 0;
|
|
fGenRenderbuffers(1, &x);
|
|
return x;
|
|
}
|
|
GLuint CreateTexture() {
|
|
GLuint x = 0;
|
|
fGenTextures(1, &x);
|
|
return x;
|
|
}
|
|
|
|
void DeleteFramebuffer(const GLuint x) { fDeleteFramebuffers(1, &x); }
|
|
void DeleteRenderbuffer(const GLuint x) { fDeleteRenderbuffers(1, &x); }
|
|
void DeleteTexture(const GLuint x) { fDeleteTextures(1, &x); }
|
|
};
|
|
|
|
bool DoesStringMatch(const char* aString, const char* aWantedString);
|
|
|
|
void SplitByChar(const nsACString& str, const char delim,
|
|
std::vector<nsCString>* const out);
|
|
|
|
template <size_t N>
|
|
bool MarkBitfieldByString(const nsACString& str,
|
|
const char* const (&markStrList)[N],
|
|
std::bitset<N>* const out_markList) {
|
|
for (size_t i = 0; i < N; i++) {
|
|
if (str.Equals(markStrList[i])) {
|
|
(*out_markList)[i] = 1;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <size_t N>
|
|
void MarkBitfieldByStrings(const std::vector<nsCString>& strList,
|
|
bool dumpStrings,
|
|
const char* const (&markStrList)[N],
|
|
std::bitset<N>* const out_markList) {
|
|
for (auto itr = strList.begin(); itr != strList.end(); ++itr) {
|
|
const nsACString& str = *itr;
|
|
const bool wasMarked = MarkBitfieldByString(str, markStrList, out_markList);
|
|
if (dumpStrings)
|
|
printf_stderr(" %s%s\n", str.BeginReading(), wasMarked ? "(*)" : "");
|
|
}
|
|
}
|
|
|
|
// -
|
|
|
|
class Renderbuffer final {
|
|
public:
|
|
const WeakPtr<GLContext> weakGl;
|
|
const GLuint name;
|
|
|
|
private:
|
|
static GLuint Create(GLContext& gl) {
|
|
GLuint ret = 0;
|
|
gl.fGenRenderbuffers(1, &ret);
|
|
return ret;
|
|
}
|
|
|
|
public:
|
|
explicit Renderbuffer(GLContext& gl) : weakGl(&gl), name(Create(gl)) {}
|
|
|
|
~Renderbuffer() {
|
|
const RefPtr<GLContext> gl = weakGl.get();
|
|
if (!gl || !gl->MakeCurrent()) return;
|
|
gl->fDeleteRenderbuffers(1, &name);
|
|
}
|
|
};
|
|
|
|
// -
|
|
|
|
class Texture final {
|
|
public:
|
|
const WeakPtr<GLContext> weakGl;
|
|
const GLuint name;
|
|
|
|
private:
|
|
static GLuint Create(GLContext& gl) {
|
|
GLuint ret = 0;
|
|
gl.fGenTextures(1, &ret);
|
|
return ret;
|
|
}
|
|
|
|
public:
|
|
explicit Texture(GLContext& gl) : weakGl(&gl), name(Create(gl)) {}
|
|
|
|
~Texture() {
|
|
const RefPtr<GLContext> gl = weakGl.get();
|
|
if (!gl || !gl->MakeCurrent()) return;
|
|
gl->fDeleteTextures(1, &name);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Helper function that creates a 2D texture aSize.width x aSize.height with
|
|
* storage type specified by aFormats. Returns GL texture object id.
|
|
*
|
|
* See mozilla::gl::CreateTexture.
|
|
*/
|
|
UniquePtr<Texture> CreateTexture(GLContext&, const gfx::IntSize& size);
|
|
|
|
/**
|
|
* Helper function that calculates the number of bytes required per
|
|
* texel for a texture from its format and type.
|
|
*/
|
|
uint32_t GetBytesPerTexel(GLenum format, GLenum type);
|
|
|
|
void MesaMemoryLeakWorkaround();
|
|
|
|
} /* namespace gl */
|
|
} /* namespace mozilla */
|
|
|
|
#endif /* GLCONTEXT_H_ */
|