/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GLCONTEXT_H_
#define GLCONTEXT_H_
#include <bitset>
#include <stdint.h>
#include <stdio.h>
#include <stack>
#include <vector>
#ifdef DEBUG
# include <string.h>
#endif
#ifdef GetClassName
# undef GetClassName
#endif
// Define MOZ_GL_DEBUG_BUILD unconditionally to enable GL debugging in opt
// builds.
#ifdef DEBUG
# define MOZ_GL_DEBUG_BUILD 1
#endif
#include "mozilla/IntegerRange.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/ThreadLocal.h"
#include "MozFramebuffer.h"
#include "nsTArray.h"
#include "GLConsts.h"
#include "GLDefs.h"
#include "GLTypes.h"
#include "nsRegionFwd.h"
#include "nsString.h"
#include "GLContextTypes.h"
#include "GLContextSymbols.h"
#include "base/platform_thread.h" // for PlatformThreadId
#include "mozilla/GenericRefCounted.h"
#include "mozilla/WeakPtr.h"
template <
class ElemT,
class... More>
constexpr
inline std::array<ElemT, 1 +
sizeof...(More)> make_array(
ElemT&& arg1, More&&... more) {
return {std::forward<ElemT>(arg1), std::forward<ElemT>(more)...};
}
#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_clamp,
depth_texture,
draw_buffers,
draw_buffers_indexed,
draw_instanced,
element_index_uint,
ES2_compatibility,
ES3_compatibility,
EXT_color_buffer_float,
frag_color_float,
frag_depth,
framebuffer_blit,
framebuffer_multisample,
framebuffer_object,
framebuffer_object_EXT_OES,
get_integer_indexed,
get_integer64_indexed,
get_query_object_i64v,
get_query_object_iv,
gpu_shader4,
instanced_arrays,
instanced_non_arrays,
internalformat_query,
invalidate_framebuffer,
map_buffer_range,
multiview,
occlusion_query,
occlusion_query_boolean,
occlusion_query2,
packed_depth_stencil,
prim_restart,
prim_restart_fixed,
provoking_vertex,
query_counter,
query_objects,
query_time_elapsed,
read_buffer,
renderbuffer_color_float,
renderbuffer_color_half_float,
robust_buffer_access_behavior,
robustness,
sRGB,
sampler_objects,
seamless_cube_map_opt_in,
shader_texture_lod,
split_framebuffer,
standard_derivatives,
sync,
texture_3D,
texture_3D_compressed,
texture_3D_copy,
texture_compression_bptc,
texture_compression_rgtc,
texture_float,
texture_float_linear,
texture_half_float,
texture_half_float_linear,
texture_non_power_of_two,
texture_norm16,
texture_rg,
texture_storage,
texture_swizzle,
transform_feedback2,
uniform_buffer_object,
uniform_matrix_nonsquare,
vertex_array_object,
EnumMax
};
enum class ContextProfile : uint8_t {
Unknown = 0,
OpenGLCore,
OpenGLCompatibility,
OpenGLES
};
enum class GLRenderer {
Adreno200,
Adreno205,
AdrenoTM200,
AdrenoTM205,
AdrenoTM305,
AdrenoTM320,
AdrenoTM330,
AdrenoTM420,
Mali400MP,
Mali450MP,
MaliT,
SGX530,
SGX540,
SGX544MP,
Tegra,
AndroidEmulator,
GalliumLlvmpipe,
IntelHD3000,
MicrosoftBasicRenderDriver,
SamsungXclipse,
Other
};
class GLContext :
public GenericAtomicRefCounted,
public SupportsWeakPtr {
public:
static MOZ_THREAD_LOCAL(
const GLContext*) sCurrentContext;
static void InvalidateCurrentContext();
const GLContextDesc mDesc;
bool mImplicitMakeCurrent =
false;
bool mUseTLSIsCurrent;
static void ResetTLSCurrentContext();
class TlsScope final {
const WeakPtr<GLContext> mGL;
const bool mWasTlsOk;
public:
explicit TlsScope(GLContext*
const gl,
bool invalidate =
false)
: mGL(gl), mWasTlsOk(gl && gl->mUseTLSIsCurrent) {
if (mGL) {
if (invalidate) {
InvalidateCurrentContext();
}
mGL->mUseTLSIsCurrent =
true;
}
}
~TlsScope() {
if (mGL) {
mGL->mUseTLSIsCurrent = mWasTlsOk;
}
}
};
// -----------------------------------------------------------------------------
// basic getters
public:
/**
* Returns true if the context is using ANGLE. This should only be overridden
* for an ANGLE implementation.
*/
virtual bool IsANGLE()
const {
return false; }
/**
* Returns true if the context is using WARP. This should only be overridden
* for an ANGLE implementation.
*/
virtual bool IsWARP()
const {
return false; }
virtual void GetWSIInfo(nsCString*
const out)
const = 0;
/**
* Return true if we are running on a OpenGL core profile context
*/
inline bool IsCoreProfile()
const {
MOZ_ASSERT(mProfile != ContextProfile::Unknown,
"unknown context profile");
return mProfile == ContextProfile::OpenGLCore;
}
/**
* Return true if we are running on a OpenGL compatibility profile context
* (legacy profile 2.1 on Max OS X)
*/
inline bool IsCompatibilityProfile()
const {
MOZ_ASSERT(mProfile != ContextProfile::Unknown,
"unknown context profile");
return mProfile == ContextProfile::OpenGLCompatibility;
}
inline bool IsGLES()
const {
MOZ_ASSERT(mProfile != ContextProfile::Unknown,
"unknown context profile");
return mProfile == ContextProfile::OpenGLES;
}
inline bool IsAtLeast(ContextProfile profile,
unsigned int version)
const {
MOZ_ASSERT(profile != ContextProfile::Unknown,
"IsAtLeast: bad 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_clamp,
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_depth_clamp,
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,
EXT_semaphore,
EXT_semaphore_fd,
EXT_memory_object,
EXT_memory_object_fd,
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 InvalidateFramebuffer(GLenum target) {
constexpr
auto ATTACHMENTS = make_array(GLenum{LOCAL_GL_COLOR_ATTACHMENT0},
LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
fInvalidateFramebuffer(target, ATTACHMENTS.size(), ATTACHMENTS.data());
}
void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments,
const GLenum* attachments) {
if (!mSymbols.fInvalidateFramebuffer)
return;
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) {
if (!mSymbols.fInvalidateSubFramebuffer)
return;
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 BindSamplerTexture(GLuint texUnitId, GLuint samplerHandle,
GLenum texTarget, GLuint texHandle) {
fBindSampler(texUnitId, samplerHandle);
fActiveTexture(LOCAL_GL_TEXTURE0 + texUnitId);
fBindTexture(texTarget, texHandle);
}
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;
// If e.g. GL_DRAW_FRAMEBUFFER isn't supported, will bind GL_FRAMEBUFFER.
void fBindFramebuffer(GLenum target,
const GLuint fb)
const {
if (!IsSupported(gl::GLFeature::framebuffer_blit)) {
target = LOCAL_GL_FRAMEBUFFER;
}
if (mElideDuplicateBindFramebuffers) {
MOZ_ASSERT(mCachedDrawFb ==
GetIntAs<GLuint>(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING));
MOZ_ASSERT(mCachedReadFb ==
GetIntAs<GLuint>(LOCAL_GL_READ_FRAMEBUFFER_BINDING));
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
if (mCachedDrawFb == fb && mCachedReadFb == fb)
return;
break;
case LOCAL_GL_DRAW_FRAMEBUFFER:
if (mCachedDrawFb == fb)
return;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
if (mCachedReadFb == fb)
return;
break;
}
}
BEFORE_GL_CALL;
mSymbols.fBindFramebuffer(target, fb);
AFTER_GL_CALL;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
mCachedDrawFb = fb;
mCachedReadFb = fb;
break;
case LOCAL_GL_DRAW_FRAMEBUFFER:
mCachedDrawFb = fb;
break;
case LOCAL_GL_READ_FRAMEBUFFER:
mCachedReadFb = fb;
break;
}
}
void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
BEFORE_GL_CALL;
mSymbols.fBindRenderbuffer(target, renderbuffer);
AFTER_GL_CALL;
}
GLenum fCheckFramebufferStatus(GLenum target) {
GLenum retval = 0;
BEFORE_GL_CALL;
retval = mSymbols.fCheckFramebufferStatus(target);
OnSyncCall();
AFTER_GL_CALL;
return retval;
}
void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint,
GLenum renderbufferTarget,
GLuint renderbuffer) {
BEFORE_GL_CALL;
mSymbols.fFramebufferRenderbuffer(target, attachmentPoint,
renderbufferTarget, renderbuffer);
AFTER_GL_CALL;
}
void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint,
GLenum textureTarget, GLuint texture,
GLint level) {
BEFORE_GL_CALL;
mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget,
texture, level);
AFTER_GL_CALL;
}
void fFramebufferTextureLayer(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLint layer) {
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fFramebufferTextureLayer);
mSymbols.fFramebufferTextureLayer(target, attachment, texture, level,
layer);
AFTER_GL_CALL;
}
void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment,
GLenum pname, GLint* value) {
BEFORE_GL_CALL;
mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname,
value);
OnSyncCall();
AFTER_GL_CALL;
}
void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
BEFORE_GL_CALL;
mSymbols.fGetRenderbufferParameteriv(target, pname, value);
OnSyncCall();
AFTER_GL_CALL;
}
realGLboolean fIsFramebuffer(GLuint framebuffer) {
realGLboolean retval =
false;
BEFORE_GL_CALL;
retval = mSymbols.fIsFramebuffer(framebuffer);
OnSyncCall();
AFTER_GL_CALL;
return retval;
}
public:
realGLboolean fIsRenderbuffer(GLuint renderbuffer) {
realGLboolean retval =
false;
BEFORE_GL_CALL;
retval = mSymbols.fIsRenderbuffer(renderbuffer);
OnSyncCall();
AFTER_GL_CALL;
return retval;
}
void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width,
GLsizei height) {
BEFORE_GL_CALL;
mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
AFTER_GL_CALL;
}
private:
void raw_fDepthRange(GLclampf a, GLclampf b) {
MOZ_ASSERT(!IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDepthRange);
mSymbols.fDepthRange(a, b);
AFTER_GL_CALL;
}
void raw_fDepthRangef(GLclampf a, GLclampf b) {
MOZ_ASSERT(IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fDepthRangef);
mSymbols.fDepthRangef(a, b);
AFTER_GL_CALL;
}
void raw_fClearDepth(GLclampf v) {
MOZ_ASSERT(!IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fClearDepth);
mSymbols.fClearDepth(v);
AFTER_GL_CALL;
}
void raw_fClearDepthf(GLclampf v) {
MOZ_ASSERT(IsGLES());
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fClearDepthf);
mSymbols.fClearDepthf(v);
AFTER_GL_CALL;
}
public:
void fDepthRange(GLclampf a, GLclampf b) {
if (IsGLES()) {
raw_fDepthRangef(a, b);
}
else {
raw_fDepthRange(a, b);
}
}
void fClearDepth(GLclampf v) {
if (IsGLES()) {
raw_fClearDepthf(v);
}
else {
raw_fClearDepth(v);
}
}
void* fMapBuffer(GLenum target, GLenum access) {
void* ret = nullptr;
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fMapBuffer);
ret = mSymbols.fMapBuffer(target, access);
OnSyncCall();
AFTER_GL_CALL;
return ret;
}
realGLboolean fUnmapBuffer(GLenum target) {
realGLboolean ret =
false;
BEFORE_GL_CALL;
ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
ret = mSymbols.fUnmapBuffer(target);
AFTER_GL_CALL;
return ret;
}
private:
GLuint raw_fCreateProgram() {
GLuint ret = 0;
BEFORE_GL_CALL;
ret = mSymbols.fCreateProgram();
AFTER_GL_CALL;
return ret;
}
GLuint raw_fCreateShader(GLenum t) {
GLuint ret = 0;
BEFORE_GL_CALL;
ret = mSymbols.fCreateShader(t);
AFTER_GL_CALL;
return ret;
}
void raw_fGenBuffers(GLsizei n, GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fGenBuffers(n, names);
OnSyncCall();
AFTER_GL_CALL;
}
void raw_fGenFramebuffers(GLsizei n, GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fGenFramebuffers(n, names);
OnSyncCall();
AFTER_GL_CALL;
}
void raw_fGenRenderbuffers(GLsizei n, GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fGenRenderbuffers(n, names);
OnSyncCall();
AFTER_GL_CALL;
}
void raw_fGenTextures(GLsizei n, GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fGenTextures(n, names);
OnSyncCall();
AFTER_GL_CALL;
}
public:
GLuint fCreateProgram() {
GLuint ret = raw_fCreateProgram();
TRACKING_CONTEXT(CreatedProgram(
this, ret));
return ret;
}
GLuint fCreateShader(GLenum t) {
GLuint ret = raw_fCreateShader(t);
TRACKING_CONTEXT(CreatedShader(
this, ret));
return ret;
}
void fGenBuffers(GLsizei n, GLuint* names) {
raw_fGenBuffers(n, names);
TRACKING_CONTEXT(CreatedBuffers(
this, n, names));
}
void fGenFramebuffers(GLsizei n, GLuint* names) {
raw_fGenFramebuffers(n, names);
TRACKING_CONTEXT(CreatedFramebuffers(
this, n, names));
}
void fGenRenderbuffers(GLsizei n, GLuint* names) {
raw_fGenRenderbuffers(n, names);
TRACKING_CONTEXT(CreatedRenderbuffers(
this, n, names));
}
void fGenTextures(GLsizei n, GLuint* names) {
raw_fGenTextures(n, names);
TRACKING_CONTEXT(CreatedTextures(
this, n, names));
}
private:
void raw_fDeleteProgram(GLuint program) {
BEFORE_GL_CALL;
mSymbols.fDeleteProgram(program);
AFTER_GL_CALL;
}
void raw_fDeleteShader(GLuint shader) {
BEFORE_GL_CALL;
mSymbols.fDeleteShader(shader);
AFTER_GL_CALL;
}
void raw_fDeleteBuffers(GLsizei n,
const GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fDeleteBuffers(n, names);
AFTER_GL_CALL;
}
void raw_fDeleteFramebuffers(GLsizei n,
const GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fDeleteFramebuffers(n, names);
AFTER_GL_CALL;
for (
const auto i : IntegerRange(n)) {
const auto fb = names[i];
if (mCachedDrawFb == fb) {
mCachedDrawFb = 0;
}
if (mCachedReadFb == fb) {
mCachedReadFb = 0;
}
}
}
void raw_fDeleteRenderbuffers(GLsizei n,
const GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fDeleteRenderbuffers(n, names);
AFTER_GL_CALL;
}
void raw_fDeleteTextures(GLsizei n,
const GLuint* names) {
BEFORE_GL_CALL;
mSymbols.fDeleteTextures(n, names);
AFTER_GL_CALL;
}
public:
void fDeleteProgram(GLuint program) {
raw_fDeleteProgram(program);
TRACKING_CONTEXT(DeletedProgram(
this, program));
}
--> --------------------
--> maximum size reached
--> --------------------