mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
02d44fddfa
Backed out changeset ea2367c19da3 (bug 952977) Backed out changeset c401c8748eb3 (bug 952977) Backed out changeset a93e9ff1043b (bug 952977) Backed out changeset 765b7f67163e (bug 952977) Backed out changeset 3d8cf4f5777f (bug 952977) Backed out changeset 8993710a3ab3 (bug 952977) Backed out changeset 1298c39b745a (bug 952977) Backed out changeset be0b899fbe5e (bug 952977) Backed out changeset f69bea1f1feb (bug 952977) Backed out changeset 1a745777f07e (bug 952977) Backed out changeset 5ad1d18dfe17 (bug 952977)
3035 lines
89 KiB
C++
3035 lines
89 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/* vim: set ts=8 sts=4 et sw=4 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef GLCONTEXT_H_
|
|
#define GLCONTEXT_H_
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <ctype.h>
|
|
#include <map>
|
|
#include <bitset>
|
|
|
|
#ifdef DEBUG
|
|
#include <string.h>
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#ifdef GetClassName
|
|
#undef GetClassName
|
|
#endif
|
|
|
|
#include "mozilla/UniquePtr.h"
|
|
|
|
#include "GLDefs.h"
|
|
#include "GLLibraryLoader.h"
|
|
#include "gfx3DMatrix.h"
|
|
#include "nsISupportsImpl.h"
|
|
#include "plstr.h"
|
|
#include "nsDataHashtable.h"
|
|
#include "nsHashKeys.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "GLContextTypes.h"
|
|
#include "GLTextureImage.h"
|
|
#include "SurfaceTypes.h"
|
|
#include "GLScreenBuffer.h"
|
|
#include "GLContextSymbols.h"
|
|
#include "base/platform_thread.h" // for PlatformThreadId
|
|
#include "mozilla/GenericRefCounted.h"
|
|
#include "gfx2DGlue.h"
|
|
|
|
class nsIntRegion;
|
|
class nsIRunnable;
|
|
class nsIThread;
|
|
|
|
namespace android {
|
|
class GraphicBuffer;
|
|
}
|
|
|
|
namespace mozilla {
|
|
namespace gfx {
|
|
class DataSourceSurface;
|
|
class SourceSurface;
|
|
}
|
|
|
|
namespace gl {
|
|
class GLContext;
|
|
class GLLibraryEGL;
|
|
class GLScreenBuffer;
|
|
class TextureGarbageBin;
|
|
class GLBlitHelper;
|
|
class GLBlitTextureImageHelper;
|
|
class GLReadTexImageHelper;
|
|
struct SurfaceCaps;
|
|
}
|
|
|
|
namespace layers {
|
|
class ColorTextureLayerProgram;
|
|
}
|
|
}
|
|
|
|
namespace mozilla {
|
|
namespace gl {
|
|
|
|
MOZ_BEGIN_ENUM_CLASS(GLFeature)
|
|
bind_buffer_offset,
|
|
blend_minmax,
|
|
depth_texture,
|
|
draw_buffers,
|
|
draw_instanced,
|
|
draw_range_elements,
|
|
element_index_uint,
|
|
ES2_compatibility,
|
|
ES3_compatibility,
|
|
frag_color_float,
|
|
frag_depth,
|
|
framebuffer_blit,
|
|
framebuffer_multisample,
|
|
framebuffer_object,
|
|
get_query_object_iv,
|
|
instanced_arrays,
|
|
instanced_non_arrays,
|
|
occlusion_query,
|
|
occlusion_query_boolean,
|
|
occlusion_query2,
|
|
packed_depth_stencil,
|
|
query_objects,
|
|
renderbuffer_color_float,
|
|
renderbuffer_color_half_float,
|
|
robustness,
|
|
sRGB,
|
|
standard_derivatives,
|
|
texture_float,
|
|
texture_float_linear,
|
|
texture_half_float,
|
|
texture_half_float_linear,
|
|
texture_non_power_of_two,
|
|
transform_feedback,
|
|
vertex_array_object,
|
|
EnumMax
|
|
MOZ_END_ENUM_CLASS(GLFeature)
|
|
|
|
MOZ_BEGIN_ENUM_CLASS(ContextProfile, uint8_t)
|
|
Unknown = 0,
|
|
OpenGL, // only for IsAtLeast's <profile> parameter
|
|
OpenGLCore,
|
|
OpenGLCompatibility,
|
|
OpenGLES
|
|
MOZ_END_ENUM_CLASS(ContextProfile)
|
|
|
|
MOZ_BEGIN_ENUM_CLASS(GLVendor)
|
|
Intel,
|
|
NVIDIA,
|
|
ATI,
|
|
Qualcomm,
|
|
Imagination,
|
|
Nouveau,
|
|
Vivante,
|
|
VMware,
|
|
Other
|
|
MOZ_END_ENUM_CLASS(GLVendor)
|
|
|
|
MOZ_BEGIN_ENUM_CLASS(GLRenderer)
|
|
Adreno200,
|
|
Adreno205,
|
|
AdrenoTM200,
|
|
AdrenoTM205,
|
|
AdrenoTM320,
|
|
SGX530,
|
|
SGX540,
|
|
Tegra,
|
|
AndroidEmulator,
|
|
GalliumLlvmpipe,
|
|
IntelHD3000,
|
|
MicrosoftBasicRenderDriver,
|
|
Other
|
|
MOZ_END_ENUM_CLASS(GLRenderer)
|
|
|
|
class GLContext
|
|
: public GLLibraryLoader
|
|
, public GenericAtomicRefCounted
|
|
{
|
|
// -----------------------------------------------------------------------------
|
|
// basic enums
|
|
public:
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// basic getters
|
|
public:
|
|
|
|
/**
|
|
* Returns true if the context is using ANGLE. This should only be overridden
|
|
* for an ANGLE implementation.
|
|
*/
|
|
virtual bool IsANGLE() const {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Return true if we are running on a OpenGL core profile context
|
|
*/
|
|
inline bool IsCoreProfile() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLCore;
|
|
}
|
|
|
|
/**
|
|
* Return true if we are running on a OpenGL compatibility profile context
|
|
* (legacy profile 2.1 on Max OS X)
|
|
*/
|
|
inline bool IsCompatibilityProfile() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLCompatibility;
|
|
}
|
|
|
|
/**
|
|
* Return true if the context is a true OpenGL ES context or an ANGLE context
|
|
*/
|
|
inline bool IsGLES() const {
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
|
|
return mProfile == ContextProfile::OpenGLES;
|
|
}
|
|
|
|
static const char* GetProfileName(ContextProfile profile)
|
|
{
|
|
switch (profile)
|
|
{
|
|
case ContextProfile::OpenGL:
|
|
return "OpenGL";
|
|
case ContextProfile::OpenGLCore:
|
|
return "OpenGL Core";
|
|
case ContextProfile::OpenGLCompatibility:
|
|
return "OpenGL Compatibility";
|
|
case ContextProfile::OpenGLES:
|
|
return "OpenGL ES";
|
|
default:
|
|
break;
|
|
}
|
|
|
|
MOZ_ASSERT(profile != ContextProfile::Unknown, "unknown context profile");
|
|
return "OpenGL unknown profile";
|
|
}
|
|
|
|
/**
|
|
* Return true if we are running on a OpenGL core profile context
|
|
*/
|
|
const char* ProfileString() const {
|
|
return GetProfileName(mProfile);
|
|
}
|
|
|
|
/**
|
|
* Return true if the context is compatible with given parameters
|
|
*
|
|
* IsAtLeast(ContextProfile::OpenGL, N) is exactly same as
|
|
* IsAtLeast(ContextProfile::OpenGLCore, N) || IsAtLeast(ContextProfile::OpenGLCompatibility, N)
|
|
*/
|
|
inline bool IsAtLeast(ContextProfile profile, unsigned int version) const
|
|
{
|
|
MOZ_ASSERT(profile != ContextProfile::Unknown, "IsAtLeast: bad <profile> parameter");
|
|
MOZ_ASSERT(mProfile != ContextProfile::Unknown, "unknown context profile");
|
|
MOZ_ASSERT(mVersion != 0, "unknown context version");
|
|
|
|
if (version > mVersion) {
|
|
return false;
|
|
}
|
|
|
|
if (profile == ContextProfile::OpenGL) {
|
|
return profile == ContextProfile::OpenGLCore ||
|
|
profile == ContextProfile::OpenGLCompatibility;
|
|
}
|
|
|
|
return profile == mProfile;
|
|
}
|
|
|
|
/**
|
|
* Return the version of the context.
|
|
* Example :
|
|
* If this a OpenGL 2.1, that will return 210
|
|
*/
|
|
inline unsigned int Version() const {
|
|
return mVersion;
|
|
}
|
|
|
|
const char* VersionString() const {
|
|
return mVersionString.get();
|
|
}
|
|
|
|
GLVendor Vendor() const {
|
|
return mVendor;
|
|
}
|
|
|
|
GLRenderer Renderer() const {
|
|
return mRenderer;
|
|
}
|
|
|
|
bool IsContextLost() const {
|
|
return mContextLost;
|
|
}
|
|
|
|
/**
|
|
* If this context is double-buffered, returns TRUE.
|
|
*/
|
|
virtual bool IsDoubleBuffered() const {
|
|
return false;
|
|
}
|
|
|
|
virtual GLContextType GetContextType() const = 0;
|
|
|
|
virtual bool IsCurrent() = 0;
|
|
|
|
protected:
|
|
|
|
bool mInitialized;
|
|
bool mIsOffscreen;
|
|
bool mIsGlobalSharedContext;
|
|
bool mContextLost;
|
|
|
|
/**
|
|
* mVersion store the OpenGL's version, multiplied by 100. For example, if
|
|
* the context is an OpenGL 2.1 context, mVersion value will be 210.
|
|
*/
|
|
unsigned int mVersion;
|
|
nsCString mVersionString;
|
|
ContextProfile mProfile;
|
|
|
|
GLVendor mVendor;
|
|
GLRenderer mRenderer;
|
|
|
|
inline void SetProfileVersion(ContextProfile profile, unsigned int version) {
|
|
MOZ_ASSERT(!mInitialized, "SetProfileVersion can only be called before initialization!");
|
|
MOZ_ASSERT(profile != ContextProfile::Unknown && profile != ContextProfile::OpenGL, "Invalid `profile` for SetProfileVersion");
|
|
MOZ_ASSERT(version >= 100, "Invalid `version` for SetProfileVersion");
|
|
|
|
mVersion = version;
|
|
mProfile = profile;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extensions management
|
|
/**
|
|
* This mechanism is designed to know if an extension is supported. In the long
|
|
* term, we would like to only use the extension group queries XXX_* to have
|
|
* full compatibility with context version and profiles (especialy the core that
|
|
* officialy don't bring any extensions).
|
|
*/
|
|
public:
|
|
|
|
/**
|
|
* Known GL extensions that can be queried by
|
|
* IsExtensionSupported. The results of this are cached, and as
|
|
* such it's safe to use this even in performance critical code.
|
|
* If you add to this array, remember to add to the string names
|
|
* in GLContext.cpp.
|
|
*/
|
|
enum GLExtensions {
|
|
Extension_None = 0,
|
|
EXT_framebuffer_object,
|
|
ARB_framebuffer_object,
|
|
ARB_texture_rectangle,
|
|
EXT_bgra,
|
|
EXT_texture_format_BGRA8888,
|
|
OES_depth24,
|
|
OES_depth32,
|
|
OES_stencil8,
|
|
OES_texture_npot,
|
|
IMG_texture_npot,
|
|
ARB_depth_texture,
|
|
OES_depth_texture,
|
|
OES_packed_depth_stencil,
|
|
IMG_read_format,
|
|
EXT_read_format_bgra,
|
|
APPLE_client_storage,
|
|
APPLE_texture_range,
|
|
ARB_texture_non_power_of_two,
|
|
ARB_pixel_buffer_object,
|
|
ARB_ES2_compatibility,
|
|
ARB_ES3_compatibility,
|
|
OES_texture_float,
|
|
OES_texture_float_linear,
|
|
ARB_texture_float,
|
|
OES_texture_half_float,
|
|
OES_texture_half_float_linear,
|
|
NV_half_float,
|
|
EXT_color_buffer_float,
|
|
EXT_color_buffer_half_float,
|
|
ARB_color_buffer_float,
|
|
EXT_unpack_subimage,
|
|
OES_standard_derivatives,
|
|
EXT_texture_filter_anisotropic,
|
|
EXT_texture_compression_s3tc,
|
|
EXT_texture_compression_dxt1,
|
|
ANGLE_texture_compression_dxt3,
|
|
ANGLE_texture_compression_dxt5,
|
|
AMD_compressed_ATC_texture,
|
|
IMG_texture_compression_pvrtc,
|
|
EXT_framebuffer_blit,
|
|
ANGLE_framebuffer_blit,
|
|
EXT_framebuffer_multisample,
|
|
ANGLE_framebuffer_multisample,
|
|
OES_rgb8_rgba8,
|
|
ARB_robustness,
|
|
EXT_robustness,
|
|
ARB_sync,
|
|
OES_EGL_image,
|
|
OES_EGL_sync,
|
|
OES_EGL_image_external,
|
|
EXT_packed_depth_stencil,
|
|
OES_element_index_uint,
|
|
OES_vertex_array_object,
|
|
ARB_vertex_array_object,
|
|
APPLE_vertex_array_object,
|
|
ARB_draw_buffers,
|
|
EXT_draw_buffers,
|
|
EXT_gpu_shader4,
|
|
EXT_blend_minmax,
|
|
ARB_draw_instanced,
|
|
EXT_draw_instanced,
|
|
NV_draw_instanced,
|
|
ARB_instanced_arrays,
|
|
NV_instanced_arrays,
|
|
ANGLE_instanced_arrays,
|
|
EXT_occlusion_query_boolean,
|
|
ARB_occlusion_query2,
|
|
EXT_transform_feedback,
|
|
NV_transform_feedback,
|
|
ANGLE_depth_texture,
|
|
EXT_sRGB,
|
|
EXT_texture_sRGB,
|
|
ARB_framebuffer_sRGB,
|
|
EXT_framebuffer_sRGB,
|
|
KHR_debug,
|
|
ARB_half_float_pixel,
|
|
EXT_frag_depth,
|
|
OES_compressed_ETC1_RGB8_texture,
|
|
EXT_draw_range_elements,
|
|
EXT_shader_texture_lod,
|
|
Extensions_Max,
|
|
Extensions_End
|
|
};
|
|
|
|
bool IsExtensionSupported(GLExtensions aKnownExtension) const {
|
|
return mAvailableExtensions[aKnownExtension];
|
|
}
|
|
|
|
void MarkExtensionUnsupported(GLExtensions aKnownExtension) {
|
|
mAvailableExtensions[aKnownExtension] = 0;
|
|
}
|
|
|
|
void MarkExtensionSupported(GLExtensions aKnownExtension) {
|
|
mAvailableExtensions[aKnownExtension] = 1;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
template<size_t N>
|
|
static void InitializeExtensionsBitSet(std::bitset<N>& extensionsBitset, const char* extStr, const char** extList, bool verbose = false)
|
|
{
|
|
char* exts = ::strdup(extStr);
|
|
|
|
if (verbose)
|
|
printf_stderr("Extensions: %s\n", exts);
|
|
|
|
char* cur = exts;
|
|
bool done = false;
|
|
while (!done) {
|
|
char* space = strchr(cur, ' ');
|
|
if (space) {
|
|
*space = '\0';
|
|
} else {
|
|
done = true;
|
|
}
|
|
|
|
for (int i = 0; extList[i]; ++i) {
|
|
if (PL_strcasecmp(cur, extList[i]) == 0) {
|
|
if (verbose)
|
|
printf_stderr("Found extension %s\n", cur);
|
|
extensionsBitset[i] = true;
|
|
}
|
|
}
|
|
|
|
cur = space + 1;
|
|
}
|
|
|
|
free(exts);
|
|
}
|
|
|
|
|
|
protected:
|
|
std::bitset<Extensions_Max> mAvailableExtensions;
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Feature queries
|
|
/*
|
|
* This mecahnism introduces a new way to check if a OpenGL feature is
|
|
* supported, regardless of whether it is supported by an extension or natively
|
|
* by the context version/profile
|
|
*/
|
|
public:
|
|
bool IsSupported(GLFeature feature) const {
|
|
return mAvailableFeatures[size_t(feature)];
|
|
}
|
|
|
|
static const char* GetFeatureName(GLFeature feature);
|
|
|
|
|
|
private:
|
|
std::bitset<size_t(GLFeature::EnumMax)> mAvailableFeatures;
|
|
|
|
/**
|
|
* Init features regarding OpenGL extension and context version and profile
|
|
*/
|
|
void InitFeatures();
|
|
|
|
/**
|
|
* Mark the feature and associated extensions as unsupported
|
|
*/
|
|
void MarkUnsupported(GLFeature feature);
|
|
|
|
/**
|
|
* Is this feature supported using the core (unsuffixed) symbols?
|
|
*/
|
|
bool IsFeatureProvidedByCoreSymbols(GLFeature feature);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Robustness handling
|
|
public:
|
|
|
|
bool HasRobustness() const {
|
|
return mHasRobustness;
|
|
}
|
|
|
|
/**
|
|
* The derived class is expected to provide information on whether or not it
|
|
* supports robustness.
|
|
*/
|
|
virtual bool SupportsRobustness() const = 0;
|
|
|
|
|
|
private:
|
|
bool mHasRobustness;
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Error handling
|
|
public:
|
|
|
|
static const char* GLErrorToString(GLenum aError)
|
|
{
|
|
switch (aError) {
|
|
case LOCAL_GL_INVALID_ENUM:
|
|
return "GL_INVALID_ENUM";
|
|
case LOCAL_GL_INVALID_VALUE:
|
|
return "GL_INVALID_VALUE";
|
|
case LOCAL_GL_INVALID_OPERATION:
|
|
return "GL_INVALID_OPERATION";
|
|
case LOCAL_GL_STACK_OVERFLOW:
|
|
return "GL_STACK_OVERFLOW";
|
|
case LOCAL_GL_STACK_UNDERFLOW:
|
|
return "GL_STACK_UNDERFLOW";
|
|
case LOCAL_GL_OUT_OF_MEMORY:
|
|
return "GL_OUT_OF_MEMORY";
|
|
case LOCAL_GL_TABLE_TOO_LARGE:
|
|
return "GL_TABLE_TOO_LARGE";
|
|
case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
|
|
/** \returns the first GL error, and guarantees that all GL error flags are cleared,
|
|
* i.e. that a subsequent GetError call will return NO_ERROR
|
|
*/
|
|
GLenum GetAndClearError()
|
|
{
|
|
// the first error is what we want to return
|
|
GLenum error = fGetError();
|
|
|
|
if (error) {
|
|
// clear all pending errors
|
|
while(fGetError()) {}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
/*** In GL debug mode, we completely override glGetError ***/
|
|
|
|
GLenum fGetError()
|
|
{
|
|
#ifdef DEBUG
|
|
// debug mode ends up eating the error in AFTER_GL_CALL
|
|
if (DebugMode()) {
|
|
GLenum err = mGLError;
|
|
mGLError = LOCAL_GL_NO_ERROR;
|
|
return err;
|
|
}
|
|
#endif // DEBUG
|
|
|
|
return mSymbols.fGetError();
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
private:
|
|
|
|
GLenum mGLError;
|
|
#endif // DEBUG
|
|
|
|
static void GLAPIENTRY StaticDebugCallback(GLenum source,
|
|
GLenum type,
|
|
GLuint id,
|
|
GLenum severity,
|
|
GLsizei length,
|
|
const GLchar* message,
|
|
const GLvoid* userParam);
|
|
void DebugCallback(GLenum source,
|
|
GLenum type,
|
|
GLuint id,
|
|
GLenum severity,
|
|
GLsizei length,
|
|
const GLchar* message);
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// MOZ_GL_DEBUG implementation
|
|
private:
|
|
|
|
#undef BEFORE_GL_CALL
|
|
#undef AFTER_GL_CALL
|
|
|
|
#ifdef DEBUG
|
|
|
|
#ifndef MOZ_FUNCTION_NAME
|
|
# ifdef __GNUC__
|
|
# define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
|
|
# elif defined(_MSC_VER)
|
|
# define MOZ_FUNCTION_NAME __FUNCTION__
|
|
# else
|
|
# define MOZ_FUNCTION_NAME __func__ // defined in C99, supported in various C++ compilers. Just raw function name.
|
|
# endif
|
|
#endif
|
|
|
|
void BeforeGLCall(const char* glFunction)
|
|
{
|
|
MOZ_ASSERT(IsCurrent());
|
|
if (DebugMode()) {
|
|
GLContext *currentGLContext = nullptr;
|
|
|
|
currentGLContext = (GLContext*)PR_GetThreadPrivate(sCurrentGLContextTLS);
|
|
|
|
if (DebugMode() & DebugTrace)
|
|
printf_stderr("[gl:%p] > %s\n", this, glFunction);
|
|
if (this != currentGLContext) {
|
|
printf_stderr("Fatal: %s called on non-current context %p. "
|
|
"The current context for this thread is %p.\n",
|
|
glFunction, this, currentGLContext);
|
|
NS_ABORT();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AfterGLCall(const char* glFunction)
|
|
{
|
|
if (DebugMode()) {
|
|
// calling fFinish() immediately after every GL call makes sure that if this GL command crashes,
|
|
// the stack trace will actually point to it. Otherwise, OpenGL being an asynchronous API, stack traces
|
|
// tend to be meaningless
|
|
mSymbols.fFinish();
|
|
mGLError = mSymbols.fGetError();
|
|
if (DebugMode() & DebugTrace)
|
|
printf_stderr("[gl:%p] < %s [0x%04x]\n", this, glFunction, mGLError);
|
|
if (mGLError != LOCAL_GL_NO_ERROR) {
|
|
printf_stderr("GL ERROR: %s generated GL error %s(0x%04x)\n",
|
|
glFunction,
|
|
GLErrorToString(mGLError),
|
|
mGLError);
|
|
if (DebugMode() & DebugAbortOnError)
|
|
NS_ABORT();
|
|
}
|
|
}
|
|
}
|
|
|
|
GLContext *TrackingContext()
|
|
{
|
|
GLContext *tip = this;
|
|
while (tip->mSharedContext)
|
|
tip = tip->mSharedContext;
|
|
return tip;
|
|
}
|
|
|
|
static void AssertNotPassingStackBufferToTheGL(const void* ptr);
|
|
|
|
#define BEFORE_GL_CALL \
|
|
do { \
|
|
BeforeGLCall(MOZ_FUNCTION_NAME); \
|
|
} while (0)
|
|
|
|
#define AFTER_GL_CALL \
|
|
do { \
|
|
AfterGLCall(MOZ_FUNCTION_NAME); \
|
|
} while (0)
|
|
|
|
#define TRACKING_CONTEXT(a) \
|
|
do { \
|
|
TrackingContext()->a; \
|
|
} while (0)
|
|
|
|
#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) AssertNotPassingStackBufferToTheGL(ptr)
|
|
|
|
#else // ifdef DEBUG
|
|
|
|
#define BEFORE_GL_CALL do { } while (0)
|
|
#define AFTER_GL_CALL do { } while (0)
|
|
#define TRACKING_CONTEXT(a) do {} while (0)
|
|
#define ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(ptr) do {} while (0)
|
|
|
|
#endif // ifdef DEBUG
|
|
|
|
#define ASSERT_SYMBOL_PRESENT(func) \
|
|
do {\
|
|
MOZ_ASSERT(strstr(MOZ_FUNCTION_NAME, #func) != nullptr, "Mismatched symbol check.");\
|
|
if (MOZ_UNLIKELY(!mSymbols.func)) {\
|
|
printf_stderr("RUNTIME ASSERT: Uninitialized GL function: %s\n", #func);\
|
|
MOZ_CRASH();\
|
|
}\
|
|
} while (0)
|
|
|
|
// Do whatever setup is necessary to draw to our offscreen FBO, if it's
|
|
// bound.
|
|
void BeforeGLDrawCall() {
|
|
}
|
|
|
|
// Do whatever tear-down is necessary after drawing to our offscreen FBO,
|
|
// if it's bound.
|
|
void AfterGLDrawCall()
|
|
{
|
|
if (mScreen)
|
|
mScreen->AfterDrawCall();
|
|
}
|
|
|
|
// Do whatever setup is necessary to read from our offscreen FBO, if it's
|
|
// bound.
|
|
void BeforeGLReadCall()
|
|
{
|
|
if (mScreen)
|
|
mScreen->BeforeReadCall();
|
|
}
|
|
|
|
// Do whatever tear-down is necessary after reading from our offscreen FBO,
|
|
// if it's bound.
|
|
void AfterGLReadCall() {
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// GL official entry points
|
|
public:
|
|
|
|
void fActiveTexture(GLenum texture) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fActiveTexture(texture);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fAttachShader(GLuint program, GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fAttachShader(program, shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBeginQuery(GLenum target, GLuint id) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBeginQuery);
|
|
mSymbols.fBeginQuery(target, id);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindAttribLocation(GLuint program, GLuint index, const GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindAttribLocation(program, index, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindBuffer(GLenum target, GLuint buffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindBuffer(target, buffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBindFramebuffer(GLenum target, GLuint framebuffer) {
|
|
if (!mScreen) {
|
|
raw_fBindFramebuffer(target, framebuffer);
|
|
return;
|
|
}
|
|
|
|
switch (target) {
|
|
case LOCAL_GL_DRAW_FRAMEBUFFER_EXT:
|
|
mScreen->BindDrawFB(framebuffer);
|
|
return;
|
|
|
|
case LOCAL_GL_READ_FRAMEBUFFER_EXT:
|
|
mScreen->BindReadFB(framebuffer);
|
|
return;
|
|
|
|
case LOCAL_GL_FRAMEBUFFER:
|
|
mScreen->BindFB(framebuffer);
|
|
return;
|
|
|
|
default:
|
|
// Nothing we care about, likely an error.
|
|
break;
|
|
}
|
|
|
|
raw_fBindFramebuffer(target, framebuffer);
|
|
}
|
|
|
|
void fBindTexture(GLenum target, GLuint texture) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindTexture(target, texture);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendColor(red, green, blue, alpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendEquation(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendEquation(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendEquationSeparate(modeRGB, modeAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendFunc(GLenum sfactor, GLenum dfactor) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendFunc(sfactor, dfactor);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(data);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBufferData(target, size, data, usage);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 fClearColor(GLclampf r, GLclampf g, GLclampf b, GLclampf 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
|
|
if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
|
|
// pass wrong values to cause the GL to generate GL_INVALID_VALUE.
|
|
// See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
|
|
level = -1;
|
|
width = -1;
|
|
height = -1;
|
|
border = -1;
|
|
}
|
|
|
|
BeforeGLReadCall();
|
|
raw_fCopyTexImage2D(target, level, internalformat,
|
|
x, y, width, height, border);
|
|
AfterGLReadCall();
|
|
}
|
|
|
|
void fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
BeforeGLReadCall();
|
|
raw_fCopyTexSubImage2D(target, level, xoffset, yoffset,
|
|
x, y, width, height);
|
|
AfterGLReadCall();
|
|
}
|
|
|
|
void fCullFace(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCullFace(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageCallback(GLDEBUGPROC callback, const GLvoid* userParam) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageCallback);
|
|
mSymbols.fDebugMessageCallback(callback, userParam);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint* ids, realGLboolean enabled) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageControl);
|
|
mSymbols.fDebugMessageControl(source, type, severity, count, ids, enabled);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* buf) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDebugMessageInsert);
|
|
mSymbols.fDebugMessageInsert(source, type, id, severity, length, buf);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDetachShader(GLuint program, GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDetachShader(program, shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDepthFunc(GLenum func) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDepthFunc(func);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDepthMask(realGLboolean flag) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDepthMask(flag);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisable(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisable(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisableClientState(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisableClientState(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDisableVertexAttribArray(GLuint index) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDisableVertexAttribArray(index);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDrawBuffer(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawBuffer(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawArrays(mode, first, count);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDrawElements(mode, count, type, indices);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawArrays(mode, first, count);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {
|
|
BeforeGLDrawCall();
|
|
raw_fDrawElements(mode, count, type, indices);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fEnable(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnable(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEnableClientState(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnableClientState(capability);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEnableVertexAttribArray(GLuint index) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fEnableVertexAttribArray(index);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEndQuery(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEndQuery);
|
|
mSymbols.fEndQuery(target);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFinish() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFinish();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFlush() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFlush();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFrontFace(GLenum face) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFrontFace(face);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveAttrib(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveAttrib(program, index, maxLength, length, size, type, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetActiveUniform(GLuint program, GLuint index, GLsizei maxLength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetActiveUniform(program, index, maxLength, length, size, type, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei* count, GLuint* shaders) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetAttachedShaders(program, maxCount, count, shaders);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLint fGetAttribLocation(GLuint program, const GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
GLint retval = mSymbols.fGetAttribLocation(program, name);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
private:
|
|
void raw_fGetIntegerv(GLenum pname, GLint *params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetIntegerv(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
|
|
void fGetIntegerv(GLenum pname, GLint *params) {
|
|
switch (pname)
|
|
{
|
|
// LOCAL_GL_FRAMEBUFFER_BINDING is equal to
|
|
// LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT,
|
|
// so we don't need two cases.
|
|
case LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT:
|
|
if (mScreen) {
|
|
*params = mScreen->GetDrawFB();
|
|
} else {
|
|
raw_fGetIntegerv(pname, params);
|
|
}
|
|
break;
|
|
|
|
case LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT:
|
|
if (mScreen) {
|
|
*params = mScreen->GetReadFB();
|
|
} else {
|
|
raw_fGetIntegerv(pname, params);
|
|
}
|
|
break;
|
|
|
|
case LOCAL_GL_MAX_TEXTURE_SIZE:
|
|
MOZ_ASSERT(mMaxTextureSize>0);
|
|
*params = mMaxTextureSize;
|
|
break;
|
|
|
|
case LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE:
|
|
MOZ_ASSERT(mMaxCubeMapTextureSize>0);
|
|
*params = mMaxCubeMapTextureSize;
|
|
break;
|
|
|
|
case LOCAL_GL_MAX_RENDERBUFFER_SIZE:
|
|
MOZ_ASSERT(mMaxRenderbufferSize>0);
|
|
*params = mMaxRenderbufferSize;
|
|
break;
|
|
|
|
case LOCAL_GL_VIEWPORT:
|
|
for (size_t i = 0; i < 4; i++) {
|
|
params[i] = mViewportRect[i];
|
|
}
|
|
break;
|
|
|
|
case LOCAL_GL_SCISSOR_BOX:
|
|
for (size_t i = 0; i < 4; i++) {
|
|
params[i] = mScissorRect[i];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
raw_fGetIntegerv(pname, params);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GetUIntegerv(GLenum pname, GLuint *params) {
|
|
fGetIntegerv(pname, reinterpret_cast<GLint*>(params));
|
|
}
|
|
|
|
void fGetFloatv(GLenum pname, GLfloat *params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetFloatv(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetBooleanv(GLenum pname, realGLboolean *params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetBooleanv(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetBufferParameteriv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLuint fGetDebugMessageLog(GLuint count, GLsizei bufsize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetDebugMessageLog);
|
|
GLuint ret = mSymbols.fGetDebugMessageLog(count, bufsize, sources, types, ids, severities, lengths, messageLog);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fGetPointerv(GLenum pname, GLvoid** params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetPointerv);
|
|
mSymbols.fGetPointerv(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetObjectLabel);
|
|
mSymbols.fGetObjectLabel(identifier, name, bufSize, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetObjectPtrLabel(const GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetObjectPtrLabel);
|
|
mSymbols.fGetObjectPtrLabel(ptr, bufSize, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGenerateMipmap(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenerateMipmap(target);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetProgramiv(GLuint program, GLenum pname, GLint* param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetProgramiv(program, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetProgramInfoLog(program, bufSize, length, infoLog);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameteri(GLenum target, GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameteri(target, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameteriv(GLenum target, GLenum pname, const GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameteriv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTexParameterf(GLenum target, GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTexParameterf(target, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
const GLubyte* fGetString(GLenum name) {
|
|
BEFORE_GL_CALL;
|
|
const GLubyte *result = mSymbols.fGetString(name);
|
|
AFTER_GL_CALL;
|
|
return result;
|
|
}
|
|
|
|
void fGetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *img) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTexImage);
|
|
mSymbols.fGetTexImage(target, level, format, type, img);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTexLevelParameteriv);
|
|
mSymbols.fGetTexLevelParameteriv(target, level, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetTexParameterfv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTexParameteriv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetTexParameteriv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetUniformfv(GLuint program, GLint location, GLfloat* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetUniformfv(program, location, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetUniformiv(GLuint program, GLint location, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetUniformiv(program, location, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLint fGetUniformLocation (GLint programObj, const GLchar* name) {
|
|
BEFORE_GL_CALL;
|
|
GLint retval = mSymbols.fGetUniformLocation(programObj, name);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribfv(index, pname, retval);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetVertexAttribiv(GLuint index, GLenum pname, GLint* retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribiv(index, pname, retval);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** retval) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetVertexAttribPointerv(index, pname, retval);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fHint(GLenum target, GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fHint(target, mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsBuffer(GLuint buffer) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsBuffer(buffer);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsEnabled(GLenum capability) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsEnabled(capability);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsProgram(program);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsShader(GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsShader(shader);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
realGLboolean fIsTexture(GLuint texture) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsTexture(texture);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fLineWidth(GLfloat width) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLineWidth(width);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLinkProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLinkProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fObjectLabel);
|
|
mSymbols.fObjectLabel(identifier, name, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fObjectPtrLabel(const GLvoid* ptr, GLsizei length, const GLchar* label) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fObjectPtrLabel);
|
|
mSymbols.fObjectPtrLabel(ptr, length, label);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLoadIdentity() {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLoadIdentity();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fLoadMatrixf(const GLfloat *matrix) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fLoadMatrixf(matrix);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fMatrixMode(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fMatrixMode(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPixelStorei(GLenum pname, GLint param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPixelStorei(pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTextureRangeAPPLE(GLenum target, GLsizei length, GLvoid *pointer) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pointer);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fTextureRangeAPPLE(target, length, pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPointParameterf(GLenum pname, GLfloat param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPointParameterf(pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPolygonOffset(GLfloat factor, GLfloat bias) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fPolygonOffset(factor, bias);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPopDebugGroup() {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPopDebugGroup);
|
|
mSymbols.fPopDebugGroup();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar* message) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fPushDebugGroup);
|
|
mSymbols.fPushDebugGroup(source, id, length, message);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fReadBuffer(GLenum mode) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fReadBuffer(mode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
|
|
ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
|
|
BeforeGLReadCall();
|
|
|
|
bool didReadPixels = false;
|
|
if (mScreen) {
|
|
didReadPixels = mScreen->ReadPixels(x, y, width, height, format, type, pixels);
|
|
}
|
|
|
|
if (!didReadPixels) {
|
|
raw_fReadPixels(x, y, width, height, format, type, pixels);
|
|
}
|
|
|
|
AfterGLReadCall();
|
|
}
|
|
|
|
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 ref, GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilFunc(func, ref, mask);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fStencilFuncSeparate(frontfunc, backfunc, ref, 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;
|
|
}
|
|
|
|
public:
|
|
void fTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
|
|
if (!IsTextureSizeSafeToPassToDriver(target, width, height)) {
|
|
// pass wrong values to cause the GL to generate GL_INVALID_VALUE.
|
|
// See bug 737182 and the comment in IsTextureSizeSafeToPassToDriver.
|
|
level = -1;
|
|
width = -1;
|
|
height = -1;
|
|
border = -1;
|
|
}
|
|
raw_fTexImage2D(target, level, internalformat, width, height, border, format, type, 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;
|
|
}
|
|
|
|
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 fUniformMatrix3fv(GLint location, GLsizei count, realGLboolean transpose, const GLfloat* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUniformMatrix3fv(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 fUseProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fUseProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fValidateProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fValidateProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttribPointer(GLuint index, GLint size, GLenum type, realGLboolean normalized, GLsizei stride, const GLvoid* pointer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttribPointer(index, size, type, normalized, stride, pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib1f(GLuint index, GLfloat x) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib1f(index, x);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib2f(index, x, y);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib3f(index, x, y, z);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib4f(index, x, y, z, w);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib1fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib1fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib2fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib2fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib3fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib3fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexAttrib4fv(GLuint index, const GLfloat* v) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexAttrib4fv(index, v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fVertexPointer(size, type, stride, pointer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fCompileShader(GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCompileShader(shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fGetShaderiv(GLuint shader, GLenum pname, GLint* param) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderiv(shader, pname, param);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderInfoLog(shader, bufSize, length, infoLog);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetShaderPrecisionFormat);
|
|
mSymbols.fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
|
if (IsGLES()) {
|
|
raw_fGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
|
|
} else {
|
|
// Fall back to automatic values because almost all desktop hardware supports the OpenGL standard precisions.
|
|
GetShaderPrecisionFormatNonES2(shadertype, precisiontype, range, precision);
|
|
}
|
|
}
|
|
|
|
void fGetShaderSource(GLint obj, GLsizei maxLength, GLsizei* length, GLchar* source) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetShaderSource(obj, maxLength, length, source);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fShaderSource(GLuint shader, GLsizei count, const GLchar** strings, const GLint* lengths) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fShaderSource(shader, count, strings, lengths);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fBindFramebuffer(GLenum target, GLuint framebuffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindFramebuffer(target, framebuffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fBindRenderbuffer(GLenum target, GLuint renderbuffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fBindRenderbuffer(target, renderbuffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLenum fCheckFramebufferStatus(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
GLenum retval = mSymbols.fCheckFramebufferStatus(target);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fFramebufferRenderbuffer(GLenum target, GLenum attachmentPoint, GLenum renderbufferTarget, GLuint renderbuffer) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFramebufferRenderbuffer(target, attachmentPoint, renderbufferTarget, renderbuffer);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fFramebufferTexture2D(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint texture, GLint level) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fFramebufferTexture2D(target, attachmentPoint, textureTarget, texture, level);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetFramebufferAttachmentParameteriv(target, attachment, pname, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* value) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGetRenderbufferParameteriv(target, pname, value);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsFramebuffer (GLuint framebuffer) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsFramebuffer(framebuffer);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
public:
|
|
realGLboolean fIsRenderbuffer (GLuint renderbuffer) {
|
|
BEFORE_GL_CALL;
|
|
realGLboolean retval = mSymbols.fIsRenderbuffer(renderbuffer);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
void fRenderbufferStorage(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fRenderbufferStorage(target, internalFormat, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
private:
|
|
void raw_fDepthRange(GLclampf a, GLclampf b) {
|
|
MOZ_ASSERT(!IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDepthRange);
|
|
mSymbols.fDepthRange(a, b);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDepthRangef(GLclampf a, GLclampf b) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDepthRangef);
|
|
mSymbols.fDepthRangef(a, b);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fClearDepth(GLclampf v) {
|
|
MOZ_ASSERT(!IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClearDepth);
|
|
mSymbols.fClearDepth(v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fClearDepthf(GLclampf v) {
|
|
MOZ_ASSERT(IsGLES());
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClearDepthf);
|
|
mSymbols.fClearDepthf(v);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
void fDepthRange(GLclampf a, GLclampf b) {
|
|
if (IsGLES()) {
|
|
raw_fDepthRangef(a, b);
|
|
} else {
|
|
raw_fDepthRange(a, b);
|
|
}
|
|
}
|
|
|
|
void fClearDepth(GLclampf v) {
|
|
if (IsGLES()) {
|
|
raw_fClearDepthf(v);
|
|
} else {
|
|
raw_fClearDepth(v);
|
|
}
|
|
}
|
|
|
|
void* fMapBuffer(GLenum target, GLenum access) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fMapBuffer);
|
|
void *ret = mSymbols.fMapBuffer(target, access);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
realGLboolean fUnmapBuffer(GLenum target) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fUnmapBuffer);
|
|
realGLboolean ret = mSymbols.fUnmapBuffer(target);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
|
|
private:
|
|
GLuint raw_fCreateProgram() {
|
|
BEFORE_GL_CALL;
|
|
GLuint ret = mSymbols.fCreateProgram();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
GLuint raw_fCreateShader(GLenum t) {
|
|
BEFORE_GL_CALL;
|
|
GLuint ret = mSymbols.fCreateShader(t);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void raw_fGenBuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenBuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenFramebuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenFramebuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenRenderbuffers(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenRenderbuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fGenTextures(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fGenTextures(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
GLuint fCreateProgram() {
|
|
GLuint ret = raw_fCreateProgram();
|
|
TRACKING_CONTEXT(CreatedProgram(this, ret));
|
|
return ret;
|
|
}
|
|
|
|
GLuint fCreateShader(GLenum t) {
|
|
GLuint ret = raw_fCreateShader(t);
|
|
TRACKING_CONTEXT(CreatedShader(this, ret));
|
|
return ret;
|
|
}
|
|
|
|
void fGenBuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenBuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedBuffers(this, n, names));
|
|
}
|
|
|
|
void fGenFramebuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenFramebuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedFramebuffers(this, n, names));
|
|
}
|
|
|
|
void fGenRenderbuffers(GLsizei n, GLuint* names) {
|
|
raw_fGenRenderbuffers(n, names);
|
|
TRACKING_CONTEXT(CreatedRenderbuffers(this, n, names));
|
|
}
|
|
|
|
void fGenTextures(GLsizei n, GLuint* names) {
|
|
raw_fGenTextures(n, names);
|
|
TRACKING_CONTEXT(CreatedTextures(this, n, names));
|
|
}
|
|
|
|
private:
|
|
void raw_fDeleteProgram(GLuint program) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteProgram(program);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteShader(GLuint shader) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteShader(shader);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteBuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteBuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteFramebuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteFramebuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteRenderbuffers(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDeleteTextures(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fDeleteTextures(n, names);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
public:
|
|
|
|
void fDeleteProgram(GLuint program) {
|
|
raw_fDeleteProgram(program);
|
|
TRACKING_CONTEXT(DeletedProgram(this, program));
|
|
}
|
|
|
|
void fDeleteShader(GLuint shader) {
|
|
raw_fDeleteShader(shader);
|
|
TRACKING_CONTEXT(DeletedShader(this, shader));
|
|
}
|
|
|
|
void fDeleteBuffers(GLsizei n, const GLuint* names) {
|
|
raw_fDeleteBuffers(n, names);
|
|
TRACKING_CONTEXT(DeletedBuffers(this, n, names));
|
|
}
|
|
|
|
void fDeleteFramebuffers(GLsizei n, const GLuint* names) {
|
|
if (mScreen) {
|
|
// Notify mScreen which framebuffers we're deleting.
|
|
// Otherwise, we will get framebuffer binding mispredictions.
|
|
for (int i = 0; i < n; i++) {
|
|
mScreen->DeletingFB(names[i]);
|
|
}
|
|
}
|
|
|
|
if (n == 1 && *names == 0) {
|
|
// Deleting framebuffer 0 causes hangs on the DROID. See bug 623228.
|
|
} else {
|
|
raw_fDeleteFramebuffers(n, names);
|
|
}
|
|
TRACKING_CONTEXT(DeletedFramebuffers(this, n, names));
|
|
}
|
|
|
|
void fDeleteRenderbuffers(GLsizei n, const GLuint* names) {
|
|
raw_fDeleteRenderbuffers(n, names);
|
|
TRACKING_CONTEXT(DeletedRenderbuffers(this, n, names));
|
|
}
|
|
|
|
void fDeleteTextures(GLsizei n, const GLuint* names) {
|
|
raw_fDeleteTextures(n, names);
|
|
TRACKING_CONTEXT(DeletedTextures(this, n, names));
|
|
}
|
|
|
|
GLenum fGetGraphicsResetStatus() {
|
|
MOZ_ASSERT(mHasRobustness);
|
|
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetGraphicsResetStatus);
|
|
GLenum ret = mSymbols.fGetGraphicsResetStatus();
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension ARB_sync (GL)
|
|
public:
|
|
GLsync fFenceSync(GLenum condition, GLbitfield flags) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fFenceSync);
|
|
GLsync ret = mSymbols.fFenceSync(condition, flags);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
realGLboolean fIsSync(GLsync sync) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsSync);
|
|
realGLboolean ret = mSymbols.fIsSync(sync);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fDeleteSync(GLsync sync) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteSync);
|
|
mSymbols.fDeleteSync(sync);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
GLenum fClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fClientWaitSync);
|
|
GLenum ret = mSymbols.fClientWaitSync(sync, flags, timeout);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
void fWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fWaitSync);
|
|
mSymbols.fWaitSync(sync, flags, timeout);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetInteger64v(GLenum pname, GLint64 *params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetInteger64v);
|
|
mSymbols.fGetInteger64v(pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetSynciv);
|
|
mSymbols.fGetSynciv(sync, pname, bufSize, length, values);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Extension OES_EGL_image (GLES)
|
|
public:
|
|
void fEGLImageTargetTexture2D(GLenum target, GLeglImage image) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEGLImageTargetTexture2D);
|
|
mSymbols.fEGLImageTargetTexture2D(target, image);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
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;
|
|
mSymbols.fDrawBuffers(n, bufs);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_draw_instanced
|
|
public:
|
|
void fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
|
|
{
|
|
BeforeGLDrawCall();
|
|
raw_fDrawArraysInstanced(mode, first, count, primcount);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
void fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei primcount)
|
|
{
|
|
BeforeGLDrawCall();
|
|
raw_fDrawElementsInstanced(mode, count, type, indices, primcount);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
private:
|
|
void raw_fDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawArraysInstanced);
|
|
mSymbols.fDrawArraysInstanced(mode, first, count, primcount);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void raw_fDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei primcount)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawElementsInstanced);
|
|
mSymbols.fDrawElementsInstanced(mode, count, type, indices, primcount);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Feature draw_range_elements
|
|
public:
|
|
void fDrawRangeElements(GLenum mode, GLuint start, GLuint end,
|
|
GLsizei count, GLenum type, const GLvoid* indices)
|
|
{
|
|
BeforeGLDrawCall();
|
|
raw_fDrawRangeElements(mode, start, end, count, type, indices);
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
private:
|
|
void raw_fDrawRangeElements(GLenum mode, GLuint start, GLuint end,
|
|
GLsizei count, GLenum type, const GLvoid* indices)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDrawRangeElements);
|
|
mSymbols.fDrawRangeElements(mode, start, end, count, type, indices);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_framebuffer_blit
|
|
public:
|
|
// Draw/Read
|
|
void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
|
BeforeGLDrawCall();
|
|
BeforeGLReadCall();
|
|
raw_fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
|
AfterGLReadCall();
|
|
AfterGLDrawCall();
|
|
}
|
|
|
|
|
|
private:
|
|
void raw_fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBlitFramebuffer);
|
|
mSymbols.fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_framebuffer_multisample
|
|
public:
|
|
void fRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fRenderbufferStorageMultisample);
|
|
mSymbols.fRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_query_objects
|
|
/**
|
|
* XXX_query_objects:
|
|
* - provide all followed entry points
|
|
*
|
|
* XXX_occlusion_query2:
|
|
* - depends on XXX_query_objects
|
|
* - provide ANY_SAMPLES_PASSED
|
|
*
|
|
* XXX_occlusion_query_boolean:
|
|
* - depends on XXX_occlusion_query2
|
|
* - provide ANY_SAMPLES_PASSED_CONSERVATIVE
|
|
*/
|
|
public:
|
|
void fDeleteQueries(GLsizei n, const GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteQueries);
|
|
mSymbols.fDeleteQueries(n, names);
|
|
AFTER_GL_CALL;
|
|
TRACKING_CONTEXT(DeletedQueries(this, n, names));
|
|
}
|
|
|
|
void fGenQueries(GLsizei n, GLuint* names) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenQueries);
|
|
mSymbols.fGenQueries(n, names);
|
|
AFTER_GL_CALL;
|
|
TRACKING_CONTEXT(CreatedQueries(this, n, names));
|
|
}
|
|
|
|
void fGetQueryiv(GLenum target, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryiv);
|
|
mSymbols.fGetQueryiv(target, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjectuiv);
|
|
mSymbols.fGetQueryObjectuiv(id, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsQuery(GLuint query) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsQuery);
|
|
realGLboolean retval = mSymbols.fIsQuery(query);
|
|
AFTER_GL_CALL;
|
|
return retval;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_get_query_object_iv
|
|
/**
|
|
* XXX_get_query_object_iv:
|
|
* - depends on XXX_query_objects
|
|
* - provide the followed entry point
|
|
*
|
|
* XXX_occlusion_query:
|
|
* - depends on XXX_get_query_object_iv
|
|
* - provide LOCAL_GL_SAMPLES_PASSED
|
|
*/
|
|
public:
|
|
void fGetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetQueryObjectiv);
|
|
mSymbols.fGetQueryObjectiv(id, pname, params);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_transform_feedback
|
|
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 fBeginTransformFeedback(GLenum primitiveMode)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBeginTransformFeedback);
|
|
mSymbols.fBeginTransformFeedback(primitiveMode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fEndTransformFeedback()
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fEndTransformFeedback);
|
|
mSymbols.fEndTransformFeedback();
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fTransformFeedbackVaryings);
|
|
mSymbols.fTransformFeedbackVaryings(program, count, varyings, bufferMode);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetTransformFeedbackVarying);
|
|
mSymbols.fGetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGetIntegeri_v(GLenum param, GLuint index, GLint* values)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGetIntegeri_v);
|
|
mSymbols.fGetIntegeri_v(param, index, values);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Package XXX_vertex_array_object
|
|
public:
|
|
void fBindVertexArray(GLuint array)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fBindVertexArray);
|
|
mSymbols.fBindVertexArray(array);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fDeleteVertexArrays(GLsizei n, const GLuint *arrays)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fDeleteVertexArrays);
|
|
mSymbols.fDeleteVertexArrays(n, arrays);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
void fGenVertexArrays(GLsizei n, GLuint *arrays)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fGenVertexArrays);
|
|
mSymbols.fGenVertexArrays(n, arrays);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
realGLboolean fIsVertexArray(GLuint array)
|
|
{
|
|
BEFORE_GL_CALL;
|
|
ASSERT_SYMBOL_PRESENT(fIsVertexArray);
|
|
realGLboolean ret = mSymbols.fIsVertexArray(array);
|
|
AFTER_GL_CALL;
|
|
return ret;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Constructor
|
|
protected:
|
|
GLContext(const SurfaceCaps& caps,
|
|
GLContext* sharedContext = nullptr,
|
|
bool isOffscreen = false);
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Destructor
|
|
public:
|
|
virtual ~GLContext();
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Everything that isn't standard GL APIs
|
|
protected:
|
|
typedef gfx::SurfaceFormat SurfaceFormat;
|
|
|
|
virtual bool MakeCurrentImpl(bool aForce) = 0;
|
|
|
|
public:
|
|
#ifdef DEBUG
|
|
static void StaticInit() {
|
|
PR_NewThreadPrivateIndex(&sCurrentGLContextTLS, nullptr);
|
|
}
|
|
#endif
|
|
|
|
bool MakeCurrent(bool aForce = false) {
|
|
if (IsDestroyed()) {
|
|
return false;
|
|
}
|
|
#ifdef DEBUG
|
|
PR_SetThreadPrivate(sCurrentGLContextTLS, this);
|
|
|
|
// XXX this assertion is disabled because it's triggering on Mac;
|
|
// we need to figure out why and reenable it.
|
|
#if 0
|
|
// IsOwningThreadCurrent is a bit of a misnomer;
|
|
// the "owning thread" is the creation thread,
|
|
// and the only thread that can own this. We don't
|
|
// support contexts used on multiple threads.
|
|
NS_ASSERTION(IsOwningThreadCurrent(),
|
|
"MakeCurrent() called on different thread than this context was created on!");
|
|
#endif
|
|
#endif
|
|
return MakeCurrentImpl(aForce);
|
|
}
|
|
|
|
virtual bool Init() = 0;
|
|
|
|
virtual bool SetupLookupFunction() = 0;
|
|
|
|
virtual void ReleaseSurface() {}
|
|
|
|
// Mark this context as destroyed. This will nullptr out all
|
|
// the GL function pointers!
|
|
void MarkDestroyed();
|
|
|
|
bool IsDestroyed() {
|
|
// MarkDestroyed will mark all these as null.
|
|
return mSymbols.fUseProgram == nullptr;
|
|
}
|
|
|
|
GLContext *GetSharedContext() { return mSharedContext; }
|
|
|
|
/**
|
|
* Returns true if the thread on which this context was created is the currently
|
|
* executing thread.
|
|
*/
|
|
bool IsOwningThreadCurrent();
|
|
|
|
static void PlatformStartup();
|
|
|
|
public:
|
|
/**
|
|
* If this context wraps a double-buffered target, swap the back
|
|
* and front buffers. It should be assumed that after a swap, the
|
|
* contents of the new back buffer are undefined.
|
|
*/
|
|
virtual bool SwapBuffers() { return false; }
|
|
|
|
/**
|
|
* Defines a two-dimensional texture image for context target surface
|
|
*/
|
|
virtual bool BindTexImage() { return false; }
|
|
/*
|
|
* Releases a color buffer that is being used as a texture
|
|
*/
|
|
virtual bool ReleaseTexImage() { return false; }
|
|
|
|
// Before reads from offscreen texture
|
|
void GuaranteeResolve();
|
|
|
|
/*
|
|
* Resize the current offscreen buffer. Returns true on success.
|
|
* If it returns false, the context should be treated as unusable
|
|
* and should be recreated. After the resize, the viewport is not
|
|
* changed; glViewport should be called as appropriate.
|
|
*
|
|
* Only valid if IsOffscreen() returns true.
|
|
*/
|
|
bool ResizeOffscreen(const gfx::IntSize& size) {
|
|
return ResizeScreenBuffer(size);
|
|
}
|
|
|
|
/*
|
|
* Return size of this offscreen context.
|
|
*
|
|
* Only valid if IsOffscreen() returns true.
|
|
*/
|
|
const gfx::IntSize& OffscreenSize() const;
|
|
|
|
void BindFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
|
|
MOZ_ASSERT(!fb || fIsFramebuffer(fb));
|
|
}
|
|
|
|
void BindDrawFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER_EXT, fb);
|
|
}
|
|
|
|
void BindReadFB(GLuint fb) {
|
|
fBindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER_EXT, fb);
|
|
}
|
|
|
|
GLuint GetDrawFB() {
|
|
if (mScreen)
|
|
return mScreen->GetDrawFB();
|
|
|
|
GLuint ret = 0;
|
|
GetUIntegerv(LOCAL_GL_DRAW_FRAMEBUFFER_BINDING_EXT, &ret);
|
|
return ret;
|
|
}
|
|
|
|
GLuint GetReadFB() {
|
|
if (mScreen)
|
|
return mScreen->GetReadFB();
|
|
|
|
GLenum bindEnum = IsSupported(GLFeature::framebuffer_blit)
|
|
? LOCAL_GL_READ_FRAMEBUFFER_BINDING_EXT
|
|
: LOCAL_GL_FRAMEBUFFER_BINDING;
|
|
|
|
GLuint ret = 0;
|
|
GetUIntegerv(bindEnum, &ret);
|
|
return ret;
|
|
}
|
|
|
|
GLuint GetFB() {
|
|
if (mScreen) {
|
|
// This has a very important extra assert that checks that we're
|
|
// not accidentally ignoring a situation where the draw and read
|
|
// FBs differ.
|
|
return mScreen->GetFB();
|
|
}
|
|
|
|
GLuint ret = 0;
|
|
GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &ret);
|
|
return ret;
|
|
}
|
|
|
|
private:
|
|
void GetShaderPrecisionFormatNonES2(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) {
|
|
switch (precisiontype) {
|
|
case LOCAL_GL_LOW_FLOAT:
|
|
case LOCAL_GL_MEDIUM_FLOAT:
|
|
case LOCAL_GL_HIGH_FLOAT:
|
|
// Assume IEEE 754 precision
|
|
range[0] = 127;
|
|
range[1] = 127;
|
|
*precision = 23;
|
|
break;
|
|
case LOCAL_GL_LOW_INT:
|
|
case LOCAL_GL_MEDIUM_INT:
|
|
case LOCAL_GL_HIGH_INT:
|
|
// Some (most) hardware only supports single-precision floating-point numbers,
|
|
// which can accurately represent integers up to +/-16777216
|
|
range[0] = 24;
|
|
range[1] = 24;
|
|
*precision = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
void ForceDirtyScreen();
|
|
void CleanDirtyScreen();
|
|
|
|
virtual GLenum GetPreferredARGB32Format() const { return LOCAL_GL_RGBA; }
|
|
|
|
virtual bool RenewSurface() { return false; }
|
|
|
|
// Shared code for GL extensions and GLX extensions.
|
|
static bool ListHasExtension(const GLubyte *extensions,
|
|
const char *extension);
|
|
|
|
GLint GetMaxTextureImageSize() { return mMaxTextureImageSize; }
|
|
|
|
public:
|
|
std::map<GLuint, SharedSurface*> mFBOMapping;
|
|
|
|
enum {
|
|
DebugEnabled = 1 << 0,
|
|
DebugTrace = 1 << 1,
|
|
DebugAbortOnError = 1 << 2
|
|
};
|
|
|
|
static uint32_t sDebugMode;
|
|
|
|
static uint32_t DebugMode() {
|
|
#ifdef DEBUG
|
|
return sDebugMode;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
protected:
|
|
nsRefPtr<GLContext> mSharedContext;
|
|
|
|
// The thread id which this context was created.
|
|
PlatformThreadId mOwningThreadId;
|
|
|
|
GLContextSymbols mSymbols;
|
|
|
|
#ifdef DEBUG
|
|
// GLDebugMode will check that we don't send call
|
|
// to a GLContext that isn't current on the current
|
|
// thread.
|
|
// Store the current context when binding to thread local
|
|
// storage to support DebugMode on an arbitrary thread.
|
|
static unsigned sCurrentGLContextTLS;
|
|
#endif
|
|
|
|
UniquePtr<GLBlitHelper> mBlitHelper;
|
|
UniquePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
|
|
UniquePtr<GLReadTexImageHelper> mReadTexImageHelper;
|
|
|
|
public:
|
|
GLBlitHelper* BlitHelper();
|
|
GLBlitTextureImageHelper* BlitTextureImageHelper();
|
|
GLReadTexImageHelper* ReadTexImageHelper();
|
|
|
|
// Assumes shares are created by all sharing with the same global context.
|
|
bool SharesWith(const GLContext* other) const {
|
|
MOZ_ASSERT(!this->mSharedContext || !this->mSharedContext->mSharedContext);
|
|
MOZ_ASSERT(!other->mSharedContext || !other->mSharedContext->mSharedContext);
|
|
MOZ_ASSERT(!this->mSharedContext ||
|
|
!other->mSharedContext ||
|
|
this->mSharedContext == other->mSharedContext);
|
|
|
|
const GLContext* thisShared = this->mSharedContext ? this->mSharedContext
|
|
: this;
|
|
const GLContext* otherShared = other->mSharedContext ? other->mSharedContext
|
|
: other;
|
|
|
|
return thisShared == otherShared;
|
|
}
|
|
|
|
bool InitOffscreen(const gfx::IntSize& size, const SurfaceCaps& caps) {
|
|
if (!CreateScreenBuffer(size, caps))
|
|
return false;
|
|
|
|
MakeCurrent();
|
|
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
|
|
fScissor(0, 0, size.width, size.height);
|
|
fViewport(0, 0, size.width, size.height);
|
|
|
|
mCaps = mScreen->mCaps;
|
|
if (mCaps.any)
|
|
DetermineCaps();
|
|
|
|
UpdateGLFormats(mCaps);
|
|
UpdatePixelFormat();
|
|
|
|
return true;
|
|
}
|
|
|
|
protected:
|
|
// Note that it does -not- clear the resized buffers.
|
|
bool CreateScreenBuffer(const gfx::IntSize& size, const SurfaceCaps& caps) {
|
|
if (!IsOffscreenSizeAllowed(size))
|
|
return false;
|
|
|
|
SurfaceCaps tryCaps = caps;
|
|
if (tryCaps.antialias) {
|
|
// AA path
|
|
if (CreateScreenBufferImpl(size, tryCaps))
|
|
return true;
|
|
|
|
NS_WARNING("CreateScreenBuffer failed to initialize an AA context! Falling back to no AA...");
|
|
tryCaps.antialias = false;
|
|
}
|
|
MOZ_ASSERT(!tryCaps.antialias);
|
|
|
|
if (CreateScreenBufferImpl(size, tryCaps))
|
|
return true;
|
|
|
|
NS_WARNING("CreateScreenBuffer failed to initialize non-AA context!");
|
|
return false;
|
|
}
|
|
|
|
bool CreateScreenBufferImpl(const gfx::IntSize& size,
|
|
const SurfaceCaps& caps);
|
|
|
|
public:
|
|
bool ResizeScreenBuffer(const gfx::IntSize& size);
|
|
|
|
protected:
|
|
SurfaceCaps mCaps;
|
|
nsAutoPtr<GLFormats> mGLFormats;
|
|
nsAutoPtr<PixelBufferFormat> mPixelFormat;
|
|
|
|
public:
|
|
void DetermineCaps();
|
|
const SurfaceCaps& Caps() const {
|
|
return mCaps;
|
|
}
|
|
|
|
// Only varies based on bpp16 and alpha.
|
|
GLFormats ChooseGLFormats(const SurfaceCaps& caps) const;
|
|
void UpdateGLFormats(const SurfaceCaps& caps) {
|
|
mGLFormats = new GLFormats(ChooseGLFormats(caps));
|
|
}
|
|
|
|
const GLFormats& GetGLFormats() const {
|
|
MOZ_ASSERT(mGLFormats);
|
|
return *mGLFormats;
|
|
}
|
|
|
|
PixelBufferFormat QueryPixelFormat();
|
|
void UpdatePixelFormat();
|
|
|
|
const PixelBufferFormat& GetPixelFormat() const {
|
|
MOZ_ASSERT(mPixelFormat);
|
|
return *mPixelFormat;
|
|
}
|
|
|
|
bool IsFramebufferComplete(GLuint fb, GLenum* status = nullptr);
|
|
|
|
// Does not check completeness.
|
|
void AttachBuffersToFB(GLuint colorTex, GLuint colorRB,
|
|
GLuint depthRB, GLuint stencilRB,
|
|
GLuint fb, GLenum target = LOCAL_GL_TEXTURE_2D);
|
|
|
|
// Passing null is fine if the value you'd get is 0.
|
|
bool AssembleOffscreenFBs(const GLuint colorMSRB,
|
|
const GLuint depthRB,
|
|
const GLuint stencilRB,
|
|
const GLuint texture,
|
|
GLuint* drawFB,
|
|
GLuint* readFB);
|
|
|
|
protected:
|
|
friend class GLScreenBuffer;
|
|
GLScreenBuffer* mScreen;
|
|
|
|
void DestroyScreenBuffer();
|
|
|
|
SharedSurface* mLockedSurface;
|
|
|
|
public:
|
|
void LockSurface(SharedSurface* surf) {
|
|
MOZ_ASSERT(!mLockedSurface);
|
|
mLockedSurface = surf;
|
|
}
|
|
|
|
void UnlockSurface(SharedSurface* surf) {
|
|
MOZ_ASSERT(mLockedSurface == surf);
|
|
mLockedSurface = nullptr;
|
|
}
|
|
|
|
SharedSurface* GetLockedSurface() const {
|
|
return mLockedSurface;
|
|
}
|
|
|
|
bool IsOffscreen() const {
|
|
return mScreen;
|
|
}
|
|
|
|
GLScreenBuffer* Screen() const {
|
|
return mScreen;
|
|
}
|
|
|
|
bool PublishFrame();
|
|
SharedSurface* RequestFrame();
|
|
|
|
/* Clear to transparent black, with 0 depth and stencil,
|
|
* while preserving current ClearColor etc. values.
|
|
* Useful for resizing offscreen buffers.
|
|
*/
|
|
void ClearSafely();
|
|
|
|
bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
|
|
|
|
protected:
|
|
nsRefPtr<TextureGarbageBin> mTexGarbageBin;
|
|
|
|
public:
|
|
TextureGarbageBin* TexGarbageBin() {
|
|
MOZ_ASSERT(mTexGarbageBin);
|
|
return mTexGarbageBin;
|
|
}
|
|
|
|
void EmptyTexGarbageBin();
|
|
|
|
bool IsOffscreenSizeAllowed(const gfx::IntSize& aSize) const;
|
|
|
|
protected:
|
|
bool InitWithPrefix(const char *prefix, bool trygl);
|
|
|
|
void InitExtensions();
|
|
|
|
GLint mViewportRect[4];
|
|
GLint mScissorRect[4];
|
|
|
|
GLint mMaxTextureSize;
|
|
GLint mMaxCubeMapTextureSize;
|
|
GLint mMaxTextureImageSize;
|
|
GLint mMaxRenderbufferSize;
|
|
GLsizei mMaxSamples;
|
|
bool mNeedsTextureSizeChecks;
|
|
bool mWorkAroundDriverBugs;
|
|
|
|
bool IsTextureSizeSafeToPassToDriver(GLenum target, GLsizei width, GLsizei height) const {
|
|
if (mNeedsTextureSizeChecks) {
|
|
// some drivers incorrectly handle some large texture sizes that are below the
|
|
// max texture size that they report. So we check ourselves against our own values
|
|
// (mMax[CubeMap]TextureSize).
|
|
// see bug 737182 for Mac Intel 2D textures
|
|
// see bug 684882 for Mac Intel cube map textures
|
|
// see bug 814716 for Mesa Nouveau
|
|
GLsizei maxSize = target == LOCAL_GL_TEXTURE_CUBE_MAP ||
|
|
(target >= LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
|
|
target <= LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
|
|
? mMaxCubeMapTextureSize
|
|
: mMaxTextureSize;
|
|
return width <= maxSize && height <= maxSize;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
void fViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|
if (mViewportRect[0] == x &&
|
|
mViewportRect[1] == y &&
|
|
mViewportRect[2] == width &&
|
|
mViewportRect[3] == height)
|
|
{
|
|
return;
|
|
}
|
|
mViewportRect[0] = x;
|
|
mViewportRect[1] = y;
|
|
mViewportRect[2] = width;
|
|
mViewportRect[3] = height;
|
|
BEFORE_GL_CALL;
|
|
mSymbols.fViewport(x, y, width, height);
|
|
AFTER_GL_CALL;
|
|
}
|
|
|
|
#undef ASSERT_SYMBOL_PRESENT
|
|
|
|
#ifdef DEBUG
|
|
void CreatedProgram(GLContext *aOrigin, GLuint aName);
|
|
void CreatedShader(GLContext *aOrigin, GLuint aName);
|
|
void CreatedBuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
|
void CreatedQueries(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
|
void CreatedTextures(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
|
void CreatedFramebuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
|
void CreatedRenderbuffers(GLContext *aOrigin, GLsizei aCount, GLuint *aNames);
|
|
void DeletedProgram(GLContext *aOrigin, GLuint aName);
|
|
void DeletedShader(GLContext *aOrigin, GLuint aName);
|
|
void DeletedBuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames);
|
|
void DeletedQueries(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames);
|
|
void DeletedTextures(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames);
|
|
void DeletedFramebuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames);
|
|
void DeletedRenderbuffers(GLContext *aOrigin, GLsizei aCount, const GLuint *aNames);
|
|
|
|
void SharedContextDestroyed(GLContext *aChild);
|
|
void ReportOutstandingNames();
|
|
|
|
struct NamedResource {
|
|
NamedResource()
|
|
: origin(nullptr), name(0), originDeleted(false)
|
|
{ }
|
|
|
|
NamedResource(GLContext *aOrigin, GLuint aName)
|
|
: origin(aOrigin), name(aName), originDeleted(false)
|
|
{ }
|
|
|
|
GLContext *origin;
|
|
GLuint name;
|
|
bool originDeleted;
|
|
|
|
// for sorting
|
|
bool operator<(const NamedResource& aOther) const {
|
|
if (intptr_t(origin) < intptr_t(aOther.origin))
|
|
return true;
|
|
if (name < aOther.name)
|
|
return true;
|
|
return false;
|
|
}
|
|
bool operator==(const NamedResource& aOther) const {
|
|
return origin == aOther.origin &&
|
|
name == aOther.name &&
|
|
originDeleted == aOther.originDeleted;
|
|
}
|
|
};
|
|
|
|
nsTArray<NamedResource> mTrackedPrograms;
|
|
nsTArray<NamedResource> mTrackedShaders;
|
|
nsTArray<NamedResource> mTrackedTextures;
|
|
nsTArray<NamedResource> mTrackedFramebuffers;
|
|
nsTArray<NamedResource> mTrackedRenderbuffers;
|
|
nsTArray<NamedResource> mTrackedBuffers;
|
|
nsTArray<NamedResource> mTrackedQueries;
|
|
#endif
|
|
};
|
|
|
|
bool DoesStringMatch(const char* aString, const char *aWantedString);
|
|
|
|
|
|
} /* namespace gl */
|
|
} /* namespace mozilla */
|
|
|
|
#endif /* GLCONTEXT_H_ */
|