2009-09-02 17:47:49 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* 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/. */
|
2009-09-17 23:01:12 -07:00
|
|
|
|
2014-05-12 19:11:40 -07:00
|
|
|
#include "WebGLContext.h"
|
|
|
|
|
2014-05-21 19:03:09 -07:00
|
|
|
#include <stdarg.h>
|
2014-05-12 19:11:40 -07:00
|
|
|
|
2014-05-21 19:03:09 -07:00
|
|
|
#include "GLContext.h"
|
2010-10-15 14:50:15 -07:00
|
|
|
#include "jsapi.h"
|
2014-05-21 19:03:09 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
2014-05-12 19:11:40 -07:00
|
|
|
#include "nsIDOMDataContainerEvent.h"
|
2014-05-21 19:03:09 -07:00
|
|
|
#include "nsIDOMEvent.h"
|
|
|
|
#include "nsIScriptSecurityManager.h"
|
|
|
|
#include "nsIVariant.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
#include "prprf.h"
|
|
|
|
#include "WebGLBuffer.h"
|
|
|
|
#include "WebGLExtensions.h"
|
|
|
|
#include "WebGLFramebuffer.h"
|
|
|
|
#include "WebGLProgram.h"
|
|
|
|
#include "WebGLTexture.h"
|
|
|
|
#include "WebGLVertexArray.h"
|
2014-08-20 13:38:42 -07:00
|
|
|
#include "WebGLContextUtils.h"
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2014-08-14 18:47:15 -07:00
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
|
|
|
|
2014-01-23 19:53:53 -08:00
|
|
|
namespace mozilla {
|
|
|
|
|
2014-05-01 20:15:58 -07:00
|
|
|
using namespace gl;
|
|
|
|
|
|
|
|
bool
|
2014-10-07 16:52:58 -07:00
|
|
|
IsGLDepthFormat(TexInternalFormat internalformat)
|
2014-05-01 20:15:58 -07:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
|
|
|
return unsizedformat == LOCAL_GL_DEPTH_COMPONENT;
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
|
|
|
|
2014-01-23 19:53:53 -08:00
|
|
|
bool
|
2014-10-07 16:52:58 -07:00
|
|
|
IsGLDepthStencilFormat(TexInternalFormat internalformat)
|
2014-01-23 19:53:53 -08:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
|
|
|
return unsizedformat == LOCAL_GL_DEPTH_STENCIL;
|
2014-01-23 19:53:53 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2014-10-07 16:52:58 -07:00
|
|
|
FormatHasAlpha(TexInternalFormat internalformat)
|
2014-05-01 20:15:58 -07:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
|
|
|
return unsizedformat == LOCAL_GL_RGBA ||
|
|
|
|
unsizedformat == LOCAL_GL_LUMINANCE_ALPHA ||
|
|
|
|
unsizedformat == LOCAL_GL_ALPHA ||
|
|
|
|
unsizedformat == LOCAL_GL_SRGB_ALPHA ||
|
|
|
|
unsizedformat == LOCAL_GL_RGBA_INTEGER;
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
2014-08-20 13:38:42 -07:00
|
|
|
|
2014-09-18 16:14:22 -07:00
|
|
|
TexTarget
|
|
|
|
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
|
2014-09-03 12:17:18 -07:00
|
|
|
{
|
2014-09-18 16:14:22 -07:00
|
|
|
switch (texImageTarget.get()) {
|
2014-09-03 12:17:18 -07:00
|
|
|
case LOCAL_GL_TEXTURE_2D:
|
2014-10-13 16:42:20 -07:00
|
|
|
case LOCAL_GL_TEXTURE_3D:
|
|
|
|
return texImageTarget.get();
|
2014-09-03 12:17:18 -07:00
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
|
|
|
|
case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
|
|
|
|
return LOCAL_GL_TEXTURE_CUBE_MAP;
|
|
|
|
default:
|
2014-10-13 16:42:20 -07:00
|
|
|
MOZ_ASSERT(false, "Bad texture target");
|
2014-09-18 16:14:22 -07:00
|
|
|
// Should be caught by the constructor for TexTarget
|
2014-09-03 12:17:18 -07:00
|
|
|
return LOCAL_GL_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
GLComponents::GLComponents(TexInternalFormat internalformat)
|
2014-08-20 13:38:42 -07:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
|
2014-08-20 13:38:42 -07:00
|
|
|
mComponents = 0;
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
switch (unsizedformat.get()) {
|
2014-08-20 13:38:42 -07:00
|
|
|
case LOCAL_GL_RGBA:
|
|
|
|
case LOCAL_GL_RGBA4:
|
|
|
|
case LOCAL_GL_RGBA8:
|
|
|
|
case LOCAL_GL_RGB5_A1:
|
|
|
|
// Luminance + Alpha can be converted
|
|
|
|
// to and from RGBA
|
|
|
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
|
|
|
mComponents |= Components::Alpha;
|
|
|
|
// Drops through
|
|
|
|
case LOCAL_GL_RGB:
|
|
|
|
case LOCAL_GL_RGB565:
|
|
|
|
// Luminance can be converted to and from RGB
|
|
|
|
case LOCAL_GL_LUMINANCE:
|
|
|
|
mComponents |= Components::Red | Components::Green | Components::Blue;
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_ALPHA:
|
|
|
|
mComponents |= Components::Alpha;
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_DEPTH_COMPONENT:
|
|
|
|
mComponents |= Components::Depth;
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_DEPTH_STENCIL:
|
|
|
|
mComponents |= Components::Stencil;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT(false, "Unhandled case - GLComponents");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
GLComponents::IsSubsetOf(const GLComponents& other) const
|
|
|
|
{
|
|
|
|
return (mComponents | other.mComponents) == other.mComponents;
|
|
|
|
}
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
TexType
|
|
|
|
TypeFromInternalFormat(TexInternalFormat internalformat)
|
|
|
|
{
|
|
|
|
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
|
|
|
if (internalformat == table_effectiveinternalformat) { \
|
|
|
|
return table_type; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "WebGLInternalFormatsTable.h"
|
|
|
|
|
|
|
|
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
|
|
|
|
return LOCAL_GL_NONE; // no size, no type
|
|
|
|
}
|
|
|
|
|
|
|
|
TexInternalFormat
|
|
|
|
UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat)
|
|
|
|
{
|
|
|
|
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
|
|
|
if (internalformat == table_effectiveinternalformat) { \
|
|
|
|
return table_internalformat; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "WebGLInternalFormatsTable.h"
|
|
|
|
|
|
|
|
// if we're here, then internalformat is not an effective internalformat i.e. is an unsized internalformat.
|
|
|
|
// so we can just return it.
|
|
|
|
return internalformat;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note that the following two functions are inverse of each other:
|
|
|
|
* EffectiveInternalFormatFromInternalFormatAndType and
|
|
|
|
* InternalFormatAndTypeFromEffectiveInternalFormat both implement OpenGL ES 3.0.3 Table 3.2
|
|
|
|
* but in opposite directions.
|
2014-05-01 20:15:58 -07:00
|
|
|
*/
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat
|
|
|
|
EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
|
|
|
|
TexType type)
|
2014-01-23 19:53:53 -08:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
MOZ_ASSERT(TypeFromInternalFormat(internalformat) == LOCAL_GL_NONE);
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
|
|
|
if (internalformat == table_internalformat && type == table_type) { \
|
|
|
|
return table_effectiveinternalformat; \
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
#include "WebGLInternalFormatsTable.h"
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
// If we're here, that means that type was incompatible with the given internalformat.
|
|
|
|
return LOCAL_GL_NONE;
|
|
|
|
}
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
void
|
|
|
|
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
|
|
|
|
TexInternalFormat* out_internalformat,
|
|
|
|
TexType* out_type)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(TypeFromInternalFormat(effectiveinternalformat) != LOCAL_GL_NONE);
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
MOZ_ASSERT(out_internalformat);
|
|
|
|
MOZ_ASSERT(out_type);
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
GLenum internalformat = LOCAL_GL_NONE;
|
|
|
|
GLenum type = LOCAL_GL_NONE;
|
|
|
|
|
|
|
|
switch (effectiveinternalformat.get()) {
|
|
|
|
|
|
|
|
#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
|
|
|
|
case table_effectiveinternalformat: \
|
|
|
|
internalformat = table_internalformat; \
|
|
|
|
type = table_type; \
|
|
|
|
break;
|
|
|
|
|
|
|
|
#include "WebGLInternalFormatsTable.h"
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_CRASH(); // impossible to get here
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
*out_internalformat = internalformat;
|
|
|
|
*out_type = type;
|
|
|
|
}
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
TexInternalFormat
|
|
|
|
EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
|
|
|
|
TexType type)
|
|
|
|
{
|
|
|
|
TexType typeOfInternalFormat = TypeFromInternalFormat(internalformat);
|
|
|
|
if (typeOfInternalFormat == LOCAL_GL_NONE) {
|
|
|
|
return EffectiveInternalFormatFromUnsizedInternalFormatAndType(internalformat, type);
|
|
|
|
} else if (typeOfInternalFormat == type) {
|
|
|
|
return internalformat;
|
|
|
|
} else {
|
|
|
|
return LOCAL_GL_NONE;
|
|
|
|
}
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
/**
|
|
|
|
* Convert effective internalformat into GL function parameters
|
|
|
|
* valid for underlying driver.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
|
|
|
|
TexInternalFormat effectiveinternalformat,
|
|
|
|
GLenum* out_driverInternalFormat,
|
|
|
|
GLenum* out_driverFormat,
|
|
|
|
GLenum* out_driverType)
|
2014-05-01 20:15:58 -07:00
|
|
|
{
|
2014-10-07 16:52:58 -07:00
|
|
|
MOZ_ASSERT(out_driverInternalFormat);
|
|
|
|
MOZ_ASSERT(out_driverFormat);
|
|
|
|
MOZ_ASSERT(out_driverType);
|
|
|
|
|
|
|
|
TexInternalFormat unsizedinternalformat = LOCAL_GL_NONE;
|
|
|
|
TexType type = LOCAL_GL_NONE;
|
2014-09-23 10:48:27 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(effectiveinternalformat,
|
|
|
|
&unsizedinternalformat, &type);
|
|
|
|
|
|
|
|
// driverType: almost always the generic type that we just got, except on ES
|
|
|
|
// we must replace HALF_FLOAT by HALF_FLOAT_OES
|
|
|
|
GLenum driverType = type.get();
|
|
|
|
if (gl->IsGLES() && type == LOCAL_GL_HALF_FLOAT) {
|
|
|
|
driverType = LOCAL_GL_HALF_FLOAT_OES;
|
|
|
|
}
|
2014-05-01 20:15:58 -07:00
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
// driverFormat: always just the unsized internalformat that we just got
|
|
|
|
GLenum driverFormat = unsizedinternalformat.get();
|
|
|
|
|
|
|
|
// driverInternalFormat: almost always the same as driverFormat, but on desktop GL,
|
|
|
|
// in some cases we must pass a different value. On ES, they are equal by definition
|
|
|
|
// as it is an error to pass internalformat!=format.
|
|
|
|
GLenum driverInternalFormat = driverFormat;
|
|
|
|
if (!gl->IsGLES()) {
|
|
|
|
// Cases where desktop OpenGL requires a tweak to 'format'
|
|
|
|
if (driverFormat == LOCAL_GL_SRGB) {
|
|
|
|
driverFormat = LOCAL_GL_RGB;
|
|
|
|
} else if (driverFormat == LOCAL_GL_SRGB_ALPHA) {
|
|
|
|
driverFormat = LOCAL_GL_RGBA;
|
|
|
|
}
|
|
|
|
|
2014-10-09 13:07:07 -07:00
|
|
|
// WebGL2's new formats are not legal values for internalformat,
|
|
|
|
// as using unsized internalformat is deprecated.
|
|
|
|
if (driverFormat == LOCAL_GL_RED ||
|
|
|
|
driverFormat == LOCAL_GL_RG ||
|
|
|
|
driverFormat == LOCAL_GL_RED_INTEGER ||
|
|
|
|
driverFormat == LOCAL_GL_RG_INTEGER ||
|
|
|
|
driverFormat == LOCAL_GL_RGB_INTEGER ||
|
|
|
|
driverFormat == LOCAL_GL_RGBA_INTEGER)
|
|
|
|
{
|
|
|
|
driverInternalFormat = effectiveinternalformat.get();
|
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
// Cases where desktop OpenGL requires a sized internalformat,
|
|
|
|
// as opposed to the unsized internalformat that had the same
|
|
|
|
// GLenum value as 'format', in order to get the precise
|
|
|
|
// semantics that we want. For example, for floating-point formats,
|
|
|
|
// we seem to need a sized internalformat to get non-clamped floating
|
|
|
|
// point texture sampling. Can't find the spec reference for that,
|
|
|
|
// but that's at least the case on my NVIDIA driver version 331.
|
|
|
|
if (unsizedinternalformat == LOCAL_GL_DEPTH_COMPONENT ||
|
|
|
|
unsizedinternalformat == LOCAL_GL_DEPTH_STENCIL ||
|
|
|
|
type == LOCAL_GL_FLOAT ||
|
|
|
|
type == LOCAL_GL_HALF_FLOAT)
|
|
|
|
{
|
|
|
|
driverInternalFormat = effectiveinternalformat.get();
|
2014-05-01 20:15:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-07 16:52:58 -07:00
|
|
|
*out_driverInternalFormat = driverInternalFormat;
|
|
|
|
*out_driverFormat = driverFormat;
|
|
|
|
*out_driverType = driverType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the bits per texel for format & type combination.
|
|
|
|
* Assumes that format & type are a valid combination as checked with
|
|
|
|
* ValidateTexImageFormatAndType().
|
|
|
|
*/
|
|
|
|
size_t
|
|
|
|
GetBitsPerTexel(TexInternalFormat effectiveinternalformat)
|
|
|
|
{
|
|
|
|
switch (effectiveinternalformat.get()) {
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_ATC_RGB:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
|
|
|
|
case LOCAL_GL_ETC1_RGB8_OES:
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
case LOCAL_GL_ALPHA8:
|
|
|
|
case LOCAL_GL_LUMINANCE8:
|
|
|
|
case LOCAL_GL_R8:
|
|
|
|
case LOCAL_GL_R8I:
|
|
|
|
case LOCAL_GL_R8UI:
|
|
|
|
case LOCAL_GL_R8_SNORM:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
|
|
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
|
|
|
|
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
|
|
|
|
return 8;
|
|
|
|
|
|
|
|
case LOCAL_GL_LUMINANCE8_ALPHA8:
|
|
|
|
case LOCAL_GL_RGBA4:
|
|
|
|
case LOCAL_GL_RGB5_A1:
|
|
|
|
case LOCAL_GL_DEPTH_COMPONENT16:
|
|
|
|
case LOCAL_GL_RG8:
|
|
|
|
case LOCAL_GL_R16I:
|
|
|
|
case LOCAL_GL_R16UI:
|
|
|
|
case LOCAL_GL_RGB565:
|
|
|
|
case LOCAL_GL_R16F:
|
|
|
|
case LOCAL_GL_RG8I:
|
|
|
|
case LOCAL_GL_RG8UI:
|
|
|
|
case LOCAL_GL_RG8_SNORM:
|
|
|
|
case LOCAL_GL_ALPHA16F_EXT:
|
|
|
|
case LOCAL_GL_LUMINANCE16F_EXT:
|
|
|
|
return 16;
|
|
|
|
|
|
|
|
case LOCAL_GL_RGB8:
|
|
|
|
case LOCAL_GL_DEPTH_COMPONENT24:
|
|
|
|
case LOCAL_GL_SRGB8:
|
|
|
|
case LOCAL_GL_RGB8UI:
|
|
|
|
case LOCAL_GL_RGB8I:
|
|
|
|
case LOCAL_GL_RGB8_SNORM:
|
|
|
|
return 24;
|
|
|
|
|
|
|
|
case LOCAL_GL_RGBA8:
|
|
|
|
case LOCAL_GL_RGB10_A2:
|
|
|
|
case LOCAL_GL_R32F:
|
|
|
|
case LOCAL_GL_RG16F:
|
|
|
|
case LOCAL_GL_R32I:
|
|
|
|
case LOCAL_GL_R32UI:
|
|
|
|
case LOCAL_GL_RG16I:
|
|
|
|
case LOCAL_GL_RG16UI:
|
|
|
|
case LOCAL_GL_DEPTH24_STENCIL8:
|
|
|
|
case LOCAL_GL_R11F_G11F_B10F:
|
|
|
|
case LOCAL_GL_RGB9_E5:
|
|
|
|
case LOCAL_GL_SRGB8_ALPHA8:
|
|
|
|
case LOCAL_GL_DEPTH_COMPONENT32F:
|
|
|
|
case LOCAL_GL_RGBA8UI:
|
|
|
|
case LOCAL_GL_RGBA8I:
|
|
|
|
case LOCAL_GL_RGBA8_SNORM:
|
|
|
|
case LOCAL_GL_RGB10_A2UI:
|
|
|
|
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
|
|
|
|
case LOCAL_GL_ALPHA32F_EXT:
|
|
|
|
case LOCAL_GL_LUMINANCE32F_EXT:
|
|
|
|
return 32;
|
|
|
|
|
|
|
|
case LOCAL_GL_DEPTH32F_STENCIL8:
|
|
|
|
return 40;
|
|
|
|
|
|
|
|
case LOCAL_GL_RGB16F:
|
|
|
|
case LOCAL_GL_RGB16UI:
|
|
|
|
case LOCAL_GL_RGB16I:
|
|
|
|
return 48;
|
|
|
|
|
|
|
|
case LOCAL_GL_RG32F:
|
|
|
|
case LOCAL_GL_RG32I:
|
|
|
|
case LOCAL_GL_RG32UI:
|
|
|
|
case LOCAL_GL_RGBA16F:
|
|
|
|
case LOCAL_GL_RGBA16UI:
|
|
|
|
case LOCAL_GL_RGBA16I:
|
|
|
|
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
|
|
|
|
return 64;
|
|
|
|
|
|
|
|
case LOCAL_GL_RGB32F:
|
|
|
|
case LOCAL_GL_RGB32UI:
|
|
|
|
case LOCAL_GL_RGB32I:
|
|
|
|
return 96;
|
|
|
|
|
|
|
|
case LOCAL_GL_RGBA32F:
|
|
|
|
case LOCAL_GL_RGBA32UI:
|
|
|
|
case LOCAL_GL_RGBA32I:
|
|
|
|
return 128;
|
|
|
|
|
|
|
|
default:
|
|
|
|
MOZ_ASSERT(false, "Unhandled format");
|
|
|
|
return 0;
|
|
|
|
}
|
2014-01-23 19:53:53 -08:00
|
|
|
}
|
|
|
|
|
2009-09-02 17:47:49 -07:00
|
|
|
void
|
2012-05-23 09:07:29 -07:00
|
|
|
WebGLContext::GenerateWarning(const char *fmt, ...)
|
2009-09-02 17:47:49 -07:00
|
|
|
{
|
2010-09-13 08:40:01 -07:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, ap);
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2010-09-13 08:40:01 -07:00
|
|
|
va_end(ap);
|
2009-09-02 17:47:49 -07:00
|
|
|
}
|
|
|
|
|
2010-05-15 06:55:45 -07:00
|
|
|
void
|
2012-05-23 09:07:29 -07:00
|
|
|
WebGLContext::GenerateWarning(const char *fmt, va_list ap)
|
2009-09-02 17:47:49 -07:00
|
|
|
{
|
2012-05-29 11:44:31 -07:00
|
|
|
if (!ShouldGenerateWarnings())
|
2012-05-23 09:07:10 -07:00
|
|
|
return;
|
|
|
|
|
2012-05-29 11:44:31 -07:00
|
|
|
mAlreadyGeneratedWarnings++;
|
2010-10-15 14:50:15 -07:00
|
|
|
|
2010-09-13 08:40:01 -07:00
|
|
|
char buf[1024];
|
2010-10-15 14:50:15 -07:00
|
|
|
PR_vsnprintf(buf, 1024, fmt, ap);
|
2010-09-13 08:40:01 -07:00
|
|
|
|
2010-10-15 14:50:15 -07:00
|
|
|
// no need to print to stderr, as JS_ReportWarning takes care of this for us.
|
|
|
|
|
2013-04-29 11:16:17 -07:00
|
|
|
AutoJSContext cx;
|
|
|
|
JS_ReportWarning(cx, "WebGL: %s", buf);
|
|
|
|
if (!ShouldGenerateWarnings()) {
|
|
|
|
JS_ReportWarning(cx,
|
|
|
|
"WebGL: No further warnings will be reported for this WebGL context "
|
|
|
|
"(already reported %d warnings)", mAlreadyGeneratedWarnings);
|
2012-05-23 09:07:10 -07:00
|
|
|
}
|
2010-09-13 08:40:01 -07:00
|
|
|
}
|
|
|
|
|
2013-09-04 05:14:50 -07:00
|
|
|
bool
|
|
|
|
WebGLContext::ShouldGenerateWarnings() const
|
|
|
|
{
|
|
|
|
if (mMaxWarnings == -1) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mAlreadyGeneratedWarnings < mMaxWarnings;
|
|
|
|
}
|
|
|
|
|
2011-09-01 12:28:34 -07:00
|
|
|
CheckedUint32
|
2014-01-23 19:52:33 -08:00
|
|
|
WebGLContext::GetImageSize(GLsizei height,
|
|
|
|
GLsizei width,
|
2014-10-13 16:42:20 -07:00
|
|
|
GLsizei depth,
|
2012-05-23 09:07:01 -07:00
|
|
|
uint32_t pixelSize,
|
|
|
|
uint32_t packOrUnpackAlignment)
|
2011-09-01 12:28:34 -07:00
|
|
|
{
|
|
|
|
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * pixelSize;
|
|
|
|
|
|
|
|
// alignedRowSize = row size rounded up to next multiple of packAlignment
|
|
|
|
CheckedUint32 checked_alignedRowSize = RoundedToNextMultipleOf(checked_plainRowSize, packOrUnpackAlignment);
|
|
|
|
|
|
|
|
// if height is 0, we don't need any memory to store this; without this check, we'll get an overflow
|
2014-10-13 16:42:20 -07:00
|
|
|
CheckedUint32 checked_2dImageSize
|
2011-09-01 12:28:34 -07:00
|
|
|
= height <= 0 ? 0 : (height-1) * checked_alignedRowSize + checked_plainRowSize;
|
|
|
|
|
2014-10-13 16:42:20 -07:00
|
|
|
// FIXME - we should honor UNPACK_IMAGE_HEIGHT
|
|
|
|
CheckedUint32 checked_imageSize = checked_2dImageSize * depth;
|
|
|
|
return checked_imageSize;
|
2011-09-01 12:28:34 -07:00
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2013-09-04 05:14:43 -07:00
|
|
|
WebGLContext::SynthesizeGLError(GLenum err)
|
2010-05-15 06:55:45 -07:00
|
|
|
{
|
2014-03-07 13:16:34 -08:00
|
|
|
/* ES2 section 2.5 "GL Errors" states that implementations can have
|
|
|
|
* multiple 'flags', as errors might be caught in different parts of
|
|
|
|
* a distributed implementation.
|
|
|
|
* We're signing up as a distributed implementation here, with
|
|
|
|
* separate flags for WebGL and the underlying GLContext.
|
|
|
|
*/
|
2011-07-07 17:01:16 -07:00
|
|
|
if (!mWebGLError)
|
|
|
|
mWebGLError = err;
|
2010-05-15 06:55:45 -07:00
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2013-09-04 05:14:43 -07:00
|
|
|
WebGLContext::SynthesizeGLError(GLenum err, const char *fmt, ...)
|
2010-05-15 06:55:45 -07:00
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2010-05-15 06:55:45 -07:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return SynthesizeGLError(err);
|
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2010-05-15 06:55:45 -07:00
|
|
|
WebGLContext::ErrorInvalidEnum(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2010-05-15 06:55:45 -07:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return SynthesizeGLError(LOCAL_GL_INVALID_ENUM);
|
|
|
|
}
|
|
|
|
|
2013-09-04 05:14:50 -07:00
|
|
|
void
|
|
|
|
WebGLContext::ErrorInvalidEnumInfo(const char *info, GLenum enumvalue)
|
|
|
|
{
|
|
|
|
return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
|
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2010-05-15 06:55:45 -07:00
|
|
|
WebGLContext::ErrorInvalidOperation(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2010-05-15 06:55:45 -07:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return SynthesizeGLError(LOCAL_GL_INVALID_OPERATION);
|
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2010-05-15 06:55:45 -07:00
|
|
|
WebGLContext::ErrorInvalidValue(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2010-05-15 06:55:45 -07:00
|
|
|
va_end(va);
|
2009-09-02 17:47:49 -07:00
|
|
|
|
2010-05-15 06:55:45 -07:00
|
|
|
return SynthesizeGLError(LOCAL_GL_INVALID_VALUE);
|
2009-09-02 17:47:49 -07:00
|
|
|
}
|
2011-02-24 14:17:34 -08:00
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2012-01-24 13:12:31 -08:00
|
|
|
WebGLContext::ErrorInvalidFramebufferOperation(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2012-01-24 13:12:31 -08:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
|
|
|
|
}
|
|
|
|
|
2012-05-04 09:38:44 -07:00
|
|
|
void
|
2011-02-24 14:17:34 -08:00
|
|
|
WebGLContext::ErrorOutOfMemory(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list va;
|
|
|
|
va_start(va, fmt);
|
2012-05-23 09:07:29 -07:00
|
|
|
GenerateWarning(fmt, va);
|
2011-02-24 14:17:34 -08:00
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
return SynthesizeGLError(LOCAL_GL_OUT_OF_MEMORY);
|
|
|
|
}
|
|
|
|
|
2011-07-07 17:01:16 -07:00
|
|
|
const char *
|
|
|
|
WebGLContext::ErrorName(GLenum error)
|
|
|
|
{
|
|
|
|
switch(error) {
|
|
|
|
case LOCAL_GL_INVALID_ENUM:
|
|
|
|
return "INVALID_ENUM";
|
|
|
|
case LOCAL_GL_INVALID_OPERATION:
|
|
|
|
return "INVALID_OPERATION";
|
|
|
|
case LOCAL_GL_INVALID_VALUE:
|
|
|
|
return "INVALID_VALUE";
|
|
|
|
case LOCAL_GL_OUT_OF_MEMORY:
|
|
|
|
return "OUT_OF_MEMORY";
|
|
|
|
case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
|
|
|
|
return "INVALID_FRAMEBUFFER_OPERATION";
|
|
|
|
case LOCAL_GL_NO_ERROR:
|
|
|
|
return "NO_ERROR";
|
|
|
|
default:
|
2013-10-11 06:16:43 -07:00
|
|
|
MOZ_ASSERT(false);
|
2011-07-07 17:01:16 -07:00
|
|
|
return "[unknown WebGL error!]";
|
|
|
|
}
|
2012-04-03 16:42:06 -07:00
|
|
|
}
|
|
|
|
|
2014-06-02 13:30:00 -07:00
|
|
|
const char*
|
|
|
|
WebGLContext::EnumName(GLenum glenum)
|
|
|
|
{
|
|
|
|
switch (glenum) {
|
|
|
|
#define XX(x) case LOCAL_GL_##x: return #x
|
|
|
|
XX(ALPHA);
|
|
|
|
XX(ATC_RGB);
|
|
|
|
XX(ATC_RGBA_EXPLICIT_ALPHA);
|
|
|
|
XX(ATC_RGBA_INTERPOLATED_ALPHA);
|
|
|
|
XX(COMPRESSED_RGBA_PVRTC_2BPPV1);
|
|
|
|
XX(COMPRESSED_RGBA_PVRTC_4BPPV1);
|
|
|
|
XX(COMPRESSED_RGBA_S3TC_DXT1_EXT);
|
|
|
|
XX(COMPRESSED_RGBA_S3TC_DXT3_EXT);
|
|
|
|
XX(COMPRESSED_RGBA_S3TC_DXT5_EXT);
|
|
|
|
XX(COMPRESSED_RGB_PVRTC_2BPPV1);
|
|
|
|
XX(COMPRESSED_RGB_PVRTC_4BPPV1);
|
|
|
|
XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
|
|
|
|
XX(DEPTH_COMPONENT);
|
|
|
|
XX(DEPTH_COMPONENT16);
|
|
|
|
XX(DEPTH_COMPONENT32);
|
|
|
|
XX(DEPTH_STENCIL);
|
|
|
|
XX(DEPTH24_STENCIL8);
|
|
|
|
XX(ETC1_RGB8_OES);
|
|
|
|
XX(FLOAT);
|
|
|
|
XX(HALF_FLOAT);
|
|
|
|
XX(LUMINANCE);
|
|
|
|
XX(LUMINANCE_ALPHA);
|
|
|
|
XX(RGB);
|
|
|
|
XX(RGB16F);
|
|
|
|
XX(RGB32F);
|
|
|
|
XX(RGBA);
|
|
|
|
XX(RGBA16F);
|
|
|
|
XX(RGBA32F);
|
|
|
|
XX(SRGB);
|
|
|
|
XX(SRGB_ALPHA);
|
|
|
|
XX(TEXTURE_2D);
|
|
|
|
XX(TEXTURE_3D);
|
|
|
|
XX(TEXTURE_CUBE_MAP);
|
|
|
|
XX(TEXTURE_CUBE_MAP_NEGATIVE_X);
|
|
|
|
XX(TEXTURE_CUBE_MAP_NEGATIVE_Y);
|
|
|
|
XX(TEXTURE_CUBE_MAP_NEGATIVE_Z);
|
|
|
|
XX(TEXTURE_CUBE_MAP_POSITIVE_X);
|
|
|
|
XX(TEXTURE_CUBE_MAP_POSITIVE_Y);
|
|
|
|
XX(TEXTURE_CUBE_MAP_POSITIVE_Z);
|
|
|
|
XX(UNSIGNED_BYTE);
|
|
|
|
XX(UNSIGNED_INT);
|
|
|
|
XX(UNSIGNED_INT_24_8);
|
|
|
|
XX(UNSIGNED_SHORT);
|
|
|
|
XX(UNSIGNED_SHORT_4_4_4_4);
|
|
|
|
XX(UNSIGNED_SHORT_5_5_5_1);
|
|
|
|
XX(UNSIGNED_SHORT_5_6_5);
|
|
|
|
#undef XX
|
|
|
|
}
|
|
|
|
|
|
|
|
return "[Unknown enum name]";
|
|
|
|
}
|
|
|
|
|
2012-04-03 16:42:06 -07:00
|
|
|
bool
|
2014-10-04 19:24:24 -07:00
|
|
|
WebGLContext::IsCompressedTextureFormat(GLenum format)
|
2012-04-03 16:42:06 -07:00
|
|
|
{
|
2014-10-04 19:24:24 -07:00
|
|
|
switch (format) {
|
2012-04-03 16:42:06 -07:00
|
|
|
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
2012-09-25 05:49:28 -07:00
|
|
|
case LOCAL_GL_ATC_RGB:
|
|
|
|
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
|
|
|
|
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
|
2012-09-25 05:49:28 -07:00
|
|
|
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
|
2014-03-10 15:42:58 -07:00
|
|
|
case LOCAL_GL_ETC1_RGB8_OES:
|
2014-07-14 16:55:56 -07:00
|
|
|
case LOCAL_GL_COMPRESSED_R11_EAC:
|
|
|
|
case LOCAL_GL_COMPRESSED_SIGNED_R11_EAC:
|
|
|
|
case LOCAL_GL_COMPRESSED_RG11_EAC:
|
|
|
|
case LOCAL_GL_COMPRESSED_SIGNED_RG11_EAC:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB8_ETC2:
|
|
|
|
case LOCAL_GL_COMPRESSED_SRGB8_ETC2:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
|
|
case LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
|
|
case LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC:
|
|
|
|
case LOCAL_GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
2012-04-03 16:42:06 -07:00
|
|
|
return true;
|
2014-01-23 19:53:53 -08:00
|
|
|
default:
|
|
|
|
return false;
|
2012-04-03 16:42:06 -07:00
|
|
|
}
|
|
|
|
}
|
2013-09-04 05:14:50 -07:00
|
|
|
|
2014-10-04 19:24:24 -07:00
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
|
|
|
|
{
|
|
|
|
return IsCompressedTextureFormat(format.get());
|
|
|
|
}
|
|
|
|
|
2014-03-07 13:16:34 -08:00
|
|
|
GLenum
|
|
|
|
WebGLContext::GetAndFlushUnderlyingGLErrors()
|
2013-09-04 05:14:50 -07:00
|
|
|
{
|
2014-03-07 13:16:34 -08:00
|
|
|
// Get and clear GL error in ALL cases.
|
2014-10-24 16:52:35 -07:00
|
|
|
GLenum error = gl->fGetError();
|
2014-03-07 13:16:34 -08:00
|
|
|
|
|
|
|
// Only store in mUnderlyingGLError if is hasn't already recorded an
|
|
|
|
// error.
|
|
|
|
if (!mUnderlyingGLError)
|
|
|
|
mUnderlyingGLError = error;
|
|
|
|
|
|
|
|
return error;
|
2013-09-04 05:14:50 -07:00
|
|
|
}
|
2014-05-21 19:03:09 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// For NaNs, etc.
|
|
|
|
static bool
|
|
|
|
IsCacheCorrect(float cached, float actual)
|
|
|
|
{
|
|
|
|
if (IsNaN(cached)) {
|
|
|
|
// GL is allowed to do anything it wants for NaNs, so if we're shadowing
|
|
|
|
// a NaN, then whatever `actual` is might be correct.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cached == actual;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow)
|
|
|
|
{
|
|
|
|
GLuint val = 0;
|
|
|
|
gl->GetUIntegerv(pname, &val);
|
|
|
|
if (val != shadow) {
|
|
|
|
printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
|
|
|
|
pname, shadow, shadow, val, val);
|
|
|
|
MOZ_ASSERT(false, "Bad cached value.");
|
|
|
|
}
|
|
|
|
}
|
2014-09-26 15:06:38 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
AssertMaskedUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint mask, GLuint shadow)
|
|
|
|
{
|
|
|
|
GLuint val = 0;
|
|
|
|
gl->GetUIntegerv(pname, &val);
|
|
|
|
|
|
|
|
const GLuint valMasked = val & mask;
|
|
|
|
const GLuint shadowMasked = shadow & mask;
|
|
|
|
|
|
|
|
if (valMasked != shadowMasked) {
|
|
|
|
printf_stderr("Failed 0x%04x shadow: Cached 0x%x/%u, should be 0x%x/%u.\n",
|
|
|
|
pname, shadowMasked, shadowMasked, valMasked, valMasked);
|
|
|
|
MOZ_ASSERT(false, "Bad cached value.");
|
|
|
|
}
|
|
|
|
}
|
2014-05-21 19:03:09 -07:00
|
|
|
#else
|
|
|
|
void
|
|
|
|
AssertUintParamCorrect(gl::GLContext*, GLenum, GLuint)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
|
|
|
WebGLContext::AssertCachedBindings()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
MakeContextCurrent();
|
|
|
|
|
|
|
|
GetAndFlushUnderlyingGLErrors();
|
|
|
|
|
|
|
|
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
|
|
|
|
GLuint bound = mBoundVertexArray ? mBoundVertexArray->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_VERTEX_ARRAY_BINDING, bound);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bound object state
|
|
|
|
GLuint bound = mBoundFramebuffer ? mBoundFramebuffer->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
|
|
|
|
|
|
|
|
bound = mCurrentProgram ? mCurrentProgram->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_CURRENT_PROGRAM, bound);
|
|
|
|
|
|
|
|
// Textures
|
|
|
|
GLenum activeTexture = mActiveTexture + LOCAL_GL_TEXTURE0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_ACTIVE_TEXTURE, activeTexture);
|
|
|
|
|
|
|
|
WebGLTexture* curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_2D);
|
|
|
|
bound = curTex ? curTex->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_2D, bound);
|
|
|
|
|
|
|
|
curTex = activeBoundTextureForTarget(LOCAL_GL_TEXTURE_CUBE_MAP);
|
|
|
|
bound = curTex ? curTex->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, bound);
|
|
|
|
|
|
|
|
// Buffers
|
|
|
|
bound = mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_ARRAY_BUFFER_BINDING, bound);
|
|
|
|
|
|
|
|
MOZ_ASSERT(mBoundVertexArray);
|
2014-06-05 16:38:27 -07:00
|
|
|
WebGLBuffer* curBuff = mBoundVertexArray->mElementArrayBuffer;
|
2014-05-21 19:03:09 -07:00
|
|
|
bound = curBuff ? curBuff->GLName() : 0;
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_ELEMENT_ARRAY_BUFFER_BINDING, bound);
|
|
|
|
|
|
|
|
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WebGLContext::AssertCachedState()
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
MakeContextCurrent();
|
|
|
|
|
|
|
|
GetAndFlushUnderlyingGLErrors();
|
|
|
|
|
|
|
|
// extensions
|
|
|
|
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_MAX_COLOR_ATTACHMENTS, mGLMaxColorAttachments);
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_MAX_DRAW_BUFFERS, mGLMaxDrawBuffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw state
|
|
|
|
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST) == mScissorTestEnabled);
|
|
|
|
MOZ_ASSERT(gl->fIsEnabled(LOCAL_GL_DITHER) == mDitherEnabled);
|
|
|
|
MOZ_ASSERT_IF(IsWebGL2(),
|
|
|
|
gl->fIsEnabled(LOCAL_GL_RASTERIZER_DISCARD) == mRasterizerDiscardEnabled);
|
|
|
|
|
|
|
|
|
|
|
|
realGLboolean colorWriteMask[4] = {0, 0, 0, 0};
|
|
|
|
gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, colorWriteMask);
|
|
|
|
MOZ_ASSERT(colorWriteMask[0] == mColorWriteMask[0] &&
|
|
|
|
colorWriteMask[1] == mColorWriteMask[1] &&
|
|
|
|
colorWriteMask[2] == mColorWriteMask[2] &&
|
|
|
|
colorWriteMask[3] == mColorWriteMask[3]);
|
|
|
|
|
|
|
|
GLfloat colorClearValue[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, colorClearValue);
|
|
|
|
MOZ_ASSERT(IsCacheCorrect(mColorClearValue[0], colorClearValue[0]) &&
|
|
|
|
IsCacheCorrect(mColorClearValue[1], colorClearValue[1]) &&
|
|
|
|
IsCacheCorrect(mColorClearValue[2], colorClearValue[2]) &&
|
|
|
|
IsCacheCorrect(mColorClearValue[3], colorClearValue[3]));
|
|
|
|
|
|
|
|
realGLboolean depthWriteMask = 0;
|
|
|
|
gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &depthWriteMask);
|
|
|
|
MOZ_ASSERT(depthWriteMask == mDepthWriteMask);
|
|
|
|
|
|
|
|
GLfloat depthClearValue = 0.0f;
|
|
|
|
gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &depthClearValue);
|
|
|
|
MOZ_ASSERT(IsCacheCorrect(mDepthClearValue, depthClearValue));
|
|
|
|
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_CLEAR_VALUE, mStencilClearValue);
|
|
|
|
|
2014-09-26 15:06:38 -07:00
|
|
|
GLint stencilBits = 0;
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_STENCIL_BITS, &stencilBits);
|
|
|
|
const GLuint stencilRefMask = (1 << stencilBits) - 1;
|
|
|
|
|
|
|
|
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_REF, stencilRefMask, mStencilRefFront);
|
|
|
|
AssertMaskedUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_REF, stencilRefMask, mStencilRefBack);
|
2014-05-21 19:03:09 -07:00
|
|
|
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_VALUE_MASK, mStencilValueMaskFront);
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_VALUE_MASK, mStencilValueMaskBack);
|
|
|
|
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_WRITEMASK, mStencilWriteMaskFront);
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_STENCIL_BACK_WRITEMASK, mStencilWriteMaskBack);
|
|
|
|
|
|
|
|
// Viewport
|
|
|
|
GLint int4[4] = {0, 0, 0, 0};
|
|
|
|
gl->fGetIntegerv(LOCAL_GL_VIEWPORT, int4);
|
|
|
|
MOZ_ASSERT(int4[0] == mViewportX &&
|
|
|
|
int4[1] == mViewportY &&
|
|
|
|
int4[2] == mViewportWidth &&
|
|
|
|
int4[3] == mViewportHeight);
|
|
|
|
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
|
|
|
|
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
|
|
|
|
|
|
|
|
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-10-13 16:42:15 -07:00
|
|
|
const char*
|
|
|
|
InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims)
|
|
|
|
{
|
|
|
|
switch (dims) {
|
|
|
|
case WebGLTexDimensions::Tex2D:
|
|
|
|
switch (func) {
|
|
|
|
case WebGLTexImageFunc::TexImage: return "texImage2D";
|
|
|
|
case WebGLTexImageFunc::TexSubImage: return "texSubImage2D";
|
|
|
|
case WebGLTexImageFunc::CopyTexImage: return "copyTexImage2D";
|
|
|
|
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage2D";
|
|
|
|
case WebGLTexImageFunc::CompTexImage: return "compressedTexImage2D";
|
|
|
|
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage2D";
|
|
|
|
default:
|
|
|
|
MOZ_CRASH();
|
|
|
|
}
|
|
|
|
case WebGLTexDimensions::Tex3D:
|
|
|
|
switch (func) {
|
2014-10-16 19:03:34 -07:00
|
|
|
case WebGLTexImageFunc::TexImage: return "texImage3D";
|
2014-10-13 16:42:15 -07:00
|
|
|
case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
|
|
|
|
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
|
|
|
|
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
|
|
|
|
default:
|
|
|
|
MOZ_CRASH();
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
MOZ_CRASH();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 19:03:09 -07:00
|
|
|
} // namespace mozilla
|