--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1767,18 +1767,21 @@ WebGLContext::DidRefresh()
bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget, GLint level,
GLenum internalformat, GLenum format, GLenum type,
mozilla::dom::Element& elt)
{
if (type == LOCAL_GL_HALF_FLOAT_OES) {
type = LOCAL_GL_HALF_FLOAT;
}
- if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
+ if (!ValidateTexImageFormatAndType(format, type,
+ WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
+ {
return false;
+ }
HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
if (!video) {
return false;
}
uint16_t readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -478,20 +478,22 @@ public:
template<class ElementType>
void TexImage2D(GLenum rawTexImgTarget, GLint level,
GLenum internalformat, GLenum format, GLenum type,
ElementType& elt, ErrorResult& rv)
{
if (IsContextLost())
return;
- auto dims = 2;
-
- if (!ValidateTexImageTarget(dims, rawTexImgTarget, WebGLTexImageFunc::TexImage))
+ if (!ValidateTexImageTarget(rawTexImgTarget,
+ WebGLTexImageFunc::TexImage,
+ WebGLTexDimensions::Tex2D))
+ {
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImgTarget);
+ }
const TexImageTarget texImageTarget(rawTexImgTarget);
if (level < 0)
return ErrorInvalidValue("texImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel)
@@ -547,18 +549,19 @@ public:
GLint xoffset, GLint yoffset,
GLenum format,
GLenum type,
ElementType& elt, ErrorResult& rv)
{
if (IsContextLost())
return;
- if (!ValidateTexImageTarget(2, rawTexImageTarget,
- WebGLTexImageFunc::TexSubImage))
+ if (!ValidateTexImageTarget(rawTexImageTarget,
+ WebGLTexImageFunc::TexSubImage,
+ WebGLTexDimensions::Tex2D))
{
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
}
const TexImageTarget texImageTarget(rawTexImageTarget);
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level is negative");
@@ -1093,60 +1096,77 @@ protected:
bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info);
bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char *info);
bool ValidateTextureTargetEnum(GLenum target, const char *info);
bool ValidateComparisonEnum(GLenum target, const char *info);
bool ValidateStencilOpEnum(GLenum action, const char *info);
bool ValidateFaceEnum(GLenum face, const char *info);
bool ValidateTexInputData(GLenum type,
js::Scalar::Type jsArrayType,
- WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateDrawModeEnum(GLenum mode, const char *info);
bool ValidateAttribIndex(GLuint index, const char *info);
bool ValidateStencilParamsForDrawCall();
bool ValidateGLSLVariableName(const nsAString& name, const char *info);
bool ValidateGLSLCharacter(char16_t c);
bool ValidateGLSLString(const nsAString& string, const char *info);
bool ValidateCopyTexImage(GLenum internalformat,
- WebGLTexImageFunc func);
- bool ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
+ bool ValidateTexImage(TexImageTarget texImageTarget,
GLint level, GLenum internalFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLint border, GLenum format, GLenum type,
- WebGLTexImageFunc func);
- bool ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
+ bool ValidateTexImageTarget(GLenum target,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateTexImageFormat(GLenum internalformat,
- WebGLTexImageFunc func);
- bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func);
- bool ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
+ bool ValidateTexImageType(GLenum type,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
+ bool ValidateTexImageFormatAndType(GLenum format,
+ GLenum type,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateCompTexImageInternalFormat(GLenum format,
- WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateCopyTexImageInternalFormat(GLenum format,
- WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateTexImageSize(TexImageTarget target, GLint level,
GLint width, GLint height, GLint depth,
- WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateTexSubImageSize(GLint x, GLint y, GLint z,
GLsizei width, GLsizei height, GLsizei depth,
GLsizei baseWidth, GLsizei baseHeight, GLsizei baseDepth,
- WebGLTexImageFunc func);
-
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateCompTexImageSize(GLint level,
GLenum internalformat,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
- WebGLTexImageFunc func);
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
bool ValidateCompTexImageDataSize(GLint level,
GLenum internalformat,
GLsizei width, GLsizei height,
- uint32_t byteLength, WebGLTexImageFunc func);
+ uint32_t byteLength,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims);
void Invalidate();
void DestroyResourcesAndContext();
void MakeContextCurrent() const;
// helpers
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -363,32 +363,35 @@ WebGLContext::CopyTexSubImage2D_base(Tex
GLsizei width,
GLsizei height,
bool sub)
{
const WebGLRectangleObject* framebufferRect = CurValidFBRectObject();
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
- const char* info = sub ? "copyTexSubImage2D" : "copyTexImage2D";
- WebGLTexImageFunc func = sub ? WebGLTexImageFunc::CopyTexSubImage : WebGLTexImageFunc::CopyTexImage;
+ WebGLTexImageFunc func = sub
+ ? WebGLTexImageFunc::CopyTexSubImage
+ : WebGLTexImageFunc::CopyTexImage;
+ WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
+ const char* info = InfoFrom(func, dims);
// TODO: This changes with color_buffer_float. Reassess when the
// patch lands.
- if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
+ if (!ValidateTexImage(texImageTarget, level, internalformat.get(),
xoffset, yoffset, 0,
width, height, 0,
0,
LOCAL_GL_NONE, LOCAL_GL_NONE,
- func))
+ func, dims))
{
return;
}
- if (!ValidateCopyTexImage(internalformat.get(), func))
+ if (!ValidateCopyTexImage(internalformat.get(), func, dims))
return;
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
MakeContextCurrent();
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
@@ -495,30 +498,31 @@ WebGLContext::CopyTexImage2D(GLenum rawT
GLsizei height,
GLint border)
{
if (IsContextLost())
return;
// copyTexImage2D only generates textures with type = UNSIGNED_BYTE
const WebGLTexImageFunc func = WebGLTexImageFunc::CopyTexImage;
-
- if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CopyTexImage))
+ const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
+
+ if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
- if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
+ if (!ValidateTexImage(rawTexImgTarget, level, internalformat,
0, 0, 0,
width, height, 0,
border, LOCAL_GL_NONE, LOCAL_GL_NONE,
- func))
+ func, dims))
{
return;
}
- if (!ValidateCopyTexImage(internalformat, func))
+ if (!ValidateCopyTexImage(internalformat, func, dims))
return;
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
CopyTexSubImage2D_base(rawTexImgTarget, level, internalformat, 0, 0, x, y, width, height, false);
}
@@ -3305,37 +3309,38 @@ WebGLContext::CompressedTexImage2D(GLenu
GLenum internalformat,
GLsizei width, GLsizei height, GLint border,
const ArrayBufferView& view)
{
if (IsContextLost())
return;
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexImage;
-
- if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CompTexImage))
+ const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
+
+ if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
- if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
+ if (!ValidateTexImage(rawTexImgTarget, level, internalformat,
0, 0, 0, width, height, 0,
border, LOCAL_GL_NONE,
LOCAL_GL_NONE,
- func))
+ func, dims))
{
return;
}
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
- if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func)) {
+ if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func, dims)) {
return;
}
- if (!ValidateCompTexImageSize(level, internalformat, 0, 0, width, height, width, height, func))
+ if (!ValidateCompTexImageSize(level, internalformat, 0, 0, width, height, width, height, func, dims))
{
return;
}
const TexImageTarget texImageTarget(rawTexImgTarget);
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex);
@@ -3357,26 +3362,27 @@ WebGLContext::CompressedTexSubImage2D(GL
GLint yoffset, GLsizei width, GLsizei height,
GLenum internalformat,
const ArrayBufferView& view)
{
if (IsContextLost())
return;
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage;
-
- if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CompTexSubImage))
+ const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
+
+ if (!ValidateTexImageTarget(rawTexImgTarget, func, dims))
return;
- if (!ValidateTexImage(2, rawTexImgTarget,
+ if (!ValidateTexImage(rawTexImgTarget,
level, internalformat,
xoffset, yoffset, 0,
width, height, 0,
0, LOCAL_GL_NONE, LOCAL_GL_NONE,
- func))
+ func, dims))
{
return;
}
const TexImageTarget texImageTarget(rawTexImgTarget);
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex);
@@ -3384,24 +3390,24 @@ WebGLContext::CompressedTexSubImage2D(GL
if (internalformat != levelInfo.EffectiveInternalFormat()) {
return ErrorInvalidOperation("compressedTexImage2D: internalformat does not match the existing image");
}
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
- if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func))
+ if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func, dims))
return;
if (!ValidateCompTexImageSize(level, internalformat,
xoffset, yoffset,
width, height,
levelInfo.Width(), levelInfo.Height(),
- func))
+ func, dims))
{
return;
}
if (levelInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
MakeContextCurrent();
@@ -3647,41 +3653,42 @@ WebGLContext::TexImage2D_base(TexImageTa
GLint border,
GLenum format,
GLenum type,
void* data, uint32_t byteLength,
js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
+ const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (type == LOCAL_GL_HALF_FLOAT_OES) {
type = LOCAL_GL_HALF_FLOAT;
}
- if (!ValidateTexImage(2, texImageTarget, level, internalformat,
+ if (!ValidateTexImage(texImageTarget, level, internalformat,
0, 0, 0,
width, height, 0,
- border, format, type, func))
+ border, format, type, func, dims))
{
return;
}
const bool isDepthTexture = format == LOCAL_GL_DEPTH_COMPONENT ||
format == LOCAL_GL_DEPTH_STENCIL;
if (isDepthTexture && !IsWebGL2()) {
if (data != nullptr || level != 0)
return ErrorInvalidOperation("texImage2D: "
"with format of DEPTH_COMPONENT or DEPTH_STENCIL, "
"data must be nullptr, "
"level must be zero");
}
- if (!ValidateTexInputData(type, jsArrayType, func))
+ if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
TexInternalFormat effectiveInternalFormat =
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
if (effectiveInternalFormat == LOCAL_GL_NONE) {
return ErrorInvalidOperation("texImage2D: bad combination of internalformat and type");
}
@@ -3811,17 +3818,17 @@ WebGLContext::TexImage2D(GLenum rawTarge
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
data = view.Data();
length = view.Length();
jsArrayType = JS_GetArrayBufferViewType(view.Obj());
}
- if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexImage))
+ if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
return;
return TexImage2D_base(rawTarget, level, internalformat, width, height, 0, border, format, type,
data, length, jsArrayType,
WebGLTexelFormat::Auto, false);
}
void
@@ -3840,17 +3847,17 @@ WebGLContext::TexImage2D(GLenum rawTarge
Uint8ClampedArray arr;
DebugOnly<bool> inited = arr.Init(pixels->GetDataObject());
MOZ_ASSERT(inited);
arr.ComputeLengthAndData();
void* pixelData = arr.Data();
const uint32_t pixelDataLength = arr.Length();
- if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexImage))
+ if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexImage, WebGLTexDimensions::Tex2D))
return;
return TexImage2D_base(rawTarget, level, internalformat, pixels->Width(),
pixels->Height(), 4*pixels->Width(), 0,
format, type, pixelData, pixelDataLength, js::Scalar::TypeMax,
WebGLTexelFormat::RGBA8, false);
}
@@ -3860,16 +3867,17 @@ WebGLContext::TexSubImage2D_base(TexImag
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
GLenum format, GLenum type,
void* data, uint32_t byteLength,
js::Scalar::Type jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
+ const WebGLTexDimensions dims = WebGLTexDimensions::Tex2D;
if (type == LOCAL_GL_HALF_FLOAT_OES) {
type = LOCAL_GL_HALF_FLOAT;
}
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
if (!tex) {
return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
@@ -3877,26 +3885,26 @@ WebGLContext::TexSubImage2D_base(TexImag
if (!tex->HasImageInfoAt(texImageTarget, level)) {
return ErrorInvalidOperation("texSubImage2D: no previously defined texture image");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
- if (!ValidateTexImage(2, texImageTarget, level,
+ if (!ValidateTexImage(texImageTarget, level,
existingEffectiveInternalFormat.get(),
xoffset, yoffset, 0,
width, height, 0,
- 0, format, type, func))
+ 0, format, type, func, dims))
{
return;
}
- if (!ValidateTexInputData(type, jsArrayType, func))
+ if (!ValidateTexInputData(type, jsArrayType, func, dims))
return;
if (type != TypeFromInternalFormat(existingEffectiveInternalFormat)) {
return ErrorInvalidOperation("texSubImage2D: type differs from that of the existing image");
}
size_t srcTexelSize = size_t(-1);
if (srcFormat == WebGLTexelFormat::Auto) {
@@ -3991,17 +3999,17 @@ WebGLContext::TexSubImage2D(GLenum rawTa
return;
if (pixels.IsNull())
return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
const ArrayBufferView& view = pixels.Value();
view.ComputeLengthAndData();
- if (!ValidateTexImageTarget(2, rawTarget, WebGLTexImageFunc::TexSubImage))
+ if (!ValidateTexImageTarget(rawTarget, WebGLTexImageFunc::TexSubImage, WebGLTexDimensions::Tex2D))
return;
return TexSubImage2D_base(rawTarget, level, xoffset, yoffset,
width, height, 0, format, type,
view.Data(), view.Length(),
JS_GetArrayBufferViewType(view.Obj()),
WebGLTexelFormat::Auto, false);
}
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -841,9 +841,37 @@ WebGLContext::AssertCachedState()
AssertUintParamCorrect(gl, LOCAL_GL_PACK_ALIGNMENT, mPixelStorePackAlignment);
AssertUintParamCorrect(gl, LOCAL_GL_UNPACK_ALIGNMENT, mPixelStoreUnpackAlignment);
MOZ_ASSERT(!GetAndFlushUnderlyingGLErrors());
#endif
}
+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) {
+ case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
+ case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
+ case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
+ default:
+ MOZ_CRASH();
+ }
+ default:
+ MOZ_CRASH();
+ }
+}
+
} // namespace mozilla
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -101,11 +101,18 @@ WebGLContext::WebGLObjectAsJSObject(JSCo
{
JS::Value v = WebGLObjectAsJSValue(cx, object, rv);
if (v.isNull()) {
return nullptr;
}
return &v.toObject();
}
+/**
+ * Return the displayable name for the texture function that is the
+ * source for validation.
+ */
+const char*
+InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims);
+
} // namespace mozilla
#endif // WEBGLCONTEXTUTILS_H_
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -56,56 +56,35 @@ BlockSizeFor(GLenum format, GLint* block
case LOCAL_GL_ETC1_RGB8_OES:
// 4x4 blocks, but no 4-multiple requirement.
default:
break;
}
}
-/**
- * Return the displayable name for the texture function that is the
- * source for validation.
- */
-static const char*
-InfoFrom(WebGLTexImageFunc func)
-{
- // TODO: Account for dimensions (WebGL 2)
- 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_ASSERT(false, "Missing case for WebGLTexImageSource");
- return "(error)";
- }
-}
-
static bool
IsCompressedFunc(WebGLTexImageFunc func)
{
return func == WebGLTexImageFunc::CompTexImage ||
func == WebGLTexImageFunc::CompTexSubImage;
}
/**
* Same as ErrorInvalidEnum but uses WebGLContext::EnumName to print displayable
* name for \a glenum.
*/
static void
-ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func)
+ErrorInvalidEnumWithName(WebGLContext* ctx, const char* msg, GLenum glenum, WebGLTexImageFunc func, WebGLTexDimensions dims)
{
const char* name = WebGLContext::EnumName(glenum);
if (name)
- ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func), msg, name);
+ ctx->ErrorInvalidEnum("%s: %s %s", InfoFrom(func, dims), msg, name);
else
- ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func), msg, glenum);
+ ctx->ErrorInvalidEnum("%s: %s 0x%04X", InfoFrom(func, dims), msg, glenum);
}
/**
* Return true if the format is valid for source calls.
*/
static bool
IsAllowedFromSource(GLenum format, WebGLTexImageFunc func)
{
@@ -381,17 +360,17 @@ WebGLContext::ValidateFramebufferAttachm
return false;
}
/**
* Return true if format is a valid texture image format for source,
* taking into account enabled WebGL extensions.
*/
bool
-WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func)
+WebGLContext::ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func, WebGLTexDimensions dims)
{
/* Core WebGL texture formats */
if (format == LOCAL_GL_ALPHA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_RGBA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_LUMINANCE_ALPHA)
{
@@ -404,103 +383,112 @@ WebGLContext::ValidateTexImageFormat(GLe
format == LOCAL_GL_RED_INTEGER ||
format == LOCAL_GL_RG_INTEGER ||
format == LOCAL_GL_RGB_INTEGER ||
format == LOCAL_GL_RGBA_INTEGER)
{
bool valid = IsWebGL2();
if (!valid) {
ErrorInvalidEnum("%s: invalid format %s: requires WebGL version 2.0 or newer",
- InfoFrom(func), EnumName(format));
+ InfoFrom(func, dims), EnumName(format));
}
return valid;
}
/* WEBGL_depth_texture added formats */
if (format == LOCAL_GL_DEPTH_COMPONENT ||
format == LOCAL_GL_DEPTH_STENCIL)
{
if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture)) {
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_depth_texture enabled",
- InfoFrom(func), EnumName(format));
+ InfoFrom(func, dims), EnumName(format));
return false;
}
// If WEBGL_depth_texture is enabled, then it is not allowed to be used with the
// copyTexImage, or copyTexSubImage methods, and it is not allowed with
// texSubImage in WebGL1.
if ((func == WebGLTexImageFunc::TexSubImage && !IsWebGL2()) ||
func == WebGLTexImageFunc::CopyTexImage ||
func == WebGLTexImageFunc::CopyTexSubImage)
{
- ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func), EnumName(format));
+ ErrorInvalidOperation("%s: format %s is not supported", InfoFrom(func, dims), EnumName(format));
return false;
}
return true;
}
// Needs to be below the depth_texture check because an invalid operation
// error needs to be generated instead of invalid enum.
/* Only core formats are valid for CopyTex(Sub)?Image */
// TODO: Revisit this once color_buffer_(half_)?float lands
if (IsCopyFunc(func)) {
- ErrorInvalidEnumWithName(this, "invalid format", format, func);
+ ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
return false;
}
/* EXT_sRGB added formats */
if (format == LOCAL_GL_SRGB ||
format == LOCAL_GL_SRGB_ALPHA)
{
bool validFormat = IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need EXT_sRGB enabled",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
- ErrorInvalidEnumWithName(this, "invalid format", format, func);
+ ErrorInvalidEnumWithName(this, "invalid format", format, func, dims);
return false;
}
/**
* Check if the given texture target is valid for TexImage.
*/
bool
-WebGLContext::ValidateTexImageTarget(GLuint dims,
- GLenum target,
- WebGLTexImageFunc func)
+WebGLContext::ValidateTexImageTarget(GLenum target,
+ WebGLTexImageFunc func, WebGLTexDimensions dims)
{
switch (dims) {
- case 2:
+ case WebGLTexDimensions::Tex2D:
if (target == LOCAL_GL_TEXTURE_2D ||
IsTexImageCubemapTarget(target))
{
return true;
}
- ErrorInvalidEnumWithName(this, "invalid target", target, func);
+ ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
+ return false;
+
+ case WebGLTexDimensions::Tex3D:
+ if (target == LOCAL_GL_TEXTURE_3D)
+ {
+ return true;
+ }
+
+ ErrorInvalidEnumWithName(this, "invalid target", target, func, dims);
return false;
default:
MOZ_ASSERT(false, "ValidateTexImageTarget: Invalid dims");
}
return false;
}
/**
* Return true if type is a valid texture image type for source,
* taking into account enabled WebGL extensions.
*/
bool
WebGLContext::ValidateTexImageType(GLenum type,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
/* Core WebGL texture types */
if (type == LOCAL_GL_UNSIGNED_BYTE ||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1)
{
return true;
@@ -513,182 +501,185 @@ WebGLContext::ValidateTexImageType(GLenu
type == LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV ||
type == LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV ||
type == LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV ||
type == LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV)
{
bool validType = IsWebGL2();
if (!validType) {
ErrorInvalidEnum("%s: invalid type %s: requires WebGL version 2.0 or newer",
- InfoFrom(func), WebGLContext::EnumName(type));
+ InfoFrom(func, dims), WebGLContext::EnumName(type));
}
return validType;
}
/* OES_texture_float added types */
if (type == LOCAL_GL_FLOAT) {
bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_float);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need OES_texture_float enabled",
- InfoFrom(func), WebGLContext::EnumName(type));
+ InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
/* OES_texture_half_float add types */
if (type == LOCAL_GL_HALF_FLOAT) {
bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need OES_texture_half_float enabled",
- InfoFrom(func), WebGLContext::EnumName(type));
+ InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
/* WEBGL_depth_texture added types */
if (type == LOCAL_GL_UNSIGNED_SHORT ||
type == LOCAL_GL_UNSIGNED_INT ||
type == LOCAL_GL_UNSIGNED_INT_24_8)
{
bool validType = IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need WEBGL_depth_texture enabled",
- InfoFrom(func), WebGLContext::EnumName(type));
+ InfoFrom(func, dims), WebGLContext::EnumName(type));
return validType;
}
- ErrorInvalidEnumWithName(this, "invalid type", type, func);
+ ErrorInvalidEnumWithName(this, "invalid type", type, func, dims);
return false;
}
/**
* Validate texture image sizing extra constraints for
* CompressedTex(Sub)?Image.
*/
// TODO: WebGL 2
bool
WebGLContext::ValidateCompTexImageSize(GLint level,
GLenum format,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
// Negative parameters must already have been handled above
MOZ_ASSERT(xoffset >= 0 && yoffset >= 0 &&
width >= 0 && height >= 0);
if (xoffset + width > (GLint) levelWidth) {
- ErrorInvalidValue("%s: xoffset + width must be <= levelWidth", InfoFrom(func));
+ ErrorInvalidValue("%s: xoffset + width must be <= levelWidth", InfoFrom(func, dims));
return false;
}
if (yoffset + height > (GLint) levelHeight) {
- ErrorInvalidValue("%s: yoffset + height must be <= levelHeight", InfoFrom(func));
+ ErrorInvalidValue("%s: yoffset + height must be <= levelHeight", InfoFrom(func, dims));
return false;
}
GLint blockWidth = 1;
GLint blockHeight = 1;
BlockSizeFor(format, &blockWidth, &blockHeight);
/* If blockWidth || blockHeight != 1, then the compressed format
* had block-based constraints to be checked. (For example, PVRTC is compressed but
* isn't a block-based format)
*/
if (blockWidth != 1 || blockHeight != 1) {
/* offsets must be multiple of block size */
if (xoffset % blockWidth != 0) {
ErrorInvalidOperation("%s: xoffset must be multiple of %d",
- InfoFrom(func), blockWidth);
+ InfoFrom(func, dims), blockWidth);
return false;
}
if (yoffset % blockHeight != 0) {
ErrorInvalidOperation("%s: yoffset must be multiple of %d",
- InfoFrom(func), blockHeight);
+ InfoFrom(func, dims), blockHeight);
return false;
}
/* The size must be a multiple of blockWidth and blockHeight,
* or must be using offset+size that exactly hits the edge.
* Important for small mipmap levels.
*/
/* https://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
* "When level equals zero width and height must be a multiple of 4. When
* level is greater than 0 width and height must be 0, 1, 2 or a multiple of 4.
* If they are not an INVALID_OPERATION error is generated."
*/
if (level == 0) {
if (width % blockWidth != 0) {
ErrorInvalidOperation("%s: width of level 0 must be multple of %d",
- InfoFrom(func), blockWidth);
+ InfoFrom(func, dims), blockWidth);
return false;
}
if (height % blockHeight != 0) {
ErrorInvalidOperation("%s: height of level 0 must be multipel of %d",
- InfoFrom(func), blockHeight);
+ InfoFrom(func, dims), blockHeight);
return false;
}
}
else if (level > 0) {
if (width % blockWidth != 0 && width > 2) {
ErrorInvalidOperation("%s: width of level %d must be multiple"
" of %d or 0, 1, 2",
- InfoFrom(func), level, blockWidth);
+ InfoFrom(func, dims), level, blockWidth);
return false;
}
if (height % blockHeight != 0 && height > 2) {
ErrorInvalidOperation("%s: height of level %d must be multiple"
" of %d or 0, 1, 2",
- InfoFrom(func), level, blockHeight);
+ InfoFrom(func, dims), level, blockHeight);
return false;
}
}
if (IsSubFunc(func)) {
if ((xoffset % blockWidth) != 0) {
ErrorInvalidOperation("%s: xoffset must be multiple of %d",
- InfoFrom(func), blockWidth);
+ InfoFrom(func, dims), blockWidth);
return false;
}
if (yoffset % blockHeight != 0) {
ErrorInvalidOperation("%s: yoffset must be multiple of %d",
- InfoFrom(func), blockHeight);
+ InfoFrom(func, dims), blockHeight);
return false;
}
}
}
switch (format) {
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:
if (!is_pot_assuming_nonnegative(width) ||
!is_pot_assuming_nonnegative(height))
{
ErrorInvalidValue("%s: width and height must be powers of two",
- InfoFrom(func));
+ InfoFrom(func, dims));
return false;
}
}
return true;
}
/**
* Return true if the enough data is present to satisfy compressed
* texture format constraints.
*/
bool
WebGLContext::ValidateCompTexImageDataSize(GLint level, GLenum format,
GLsizei width, GLsizei height,
- uint32_t byteLength, WebGLTexImageFunc func)
+ uint32_t byteLength,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
// negative width and height must already have been handled above
MOZ_ASSERT(width >= 0 && height >= 0);
CheckedUint32 required_byteLength = 0;
switch (format) {
case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
@@ -717,33 +708,33 @@ WebGLContext::ValidateCompTexImageDataSi
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
{
required_byteLength = CheckedUint32(std::max(width, 16)) * CheckedUint32(std::max(height, 8)) / 4;
break;
}
}
if (!required_byteLength.isValid() || required_byteLength.value() != byteLength) {
- ErrorInvalidValue("%s: data size does not match dimensions", InfoFrom(func));
+ ErrorInvalidValue("%s: data size does not match dimensions", InfoFrom(func, dims));
return false;
}
return true;
}
/**
* Validate the width, height, and depth of a texture image, \return
* true is valid, false otherwise.
* Used by all the (Compressed|Copy)?Tex(Sub)?Image functions.
* Target and level must have been validated before calling.
*/
bool
WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
GLint width, GLint height, GLint depth,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func, WebGLTexDimensions dims)
{
MOZ_ASSERT(level >= 0, "level should already be validated");
/* Bug 966630: maxTextureSize >> level runs into "undefined"
* behaviour depending on ISA. For example, on Intel shifts
* amounts are mod 64 (in 64-bit mode on 64-bit dest) and mod 32
* otherwise. This means 16384 >> 0x10000001 == 8192 which isn't
* what would be expected. Make the required behaviour explicit by
@@ -761,262 +752,267 @@ WebGLContext::ValidateTexImageSize(TexIm
if (!isSub && isCubemapTarget && (width != height)) {
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "When the target parameter to TexImage2D is one of the
* six cube map two-dimensional image targets, the error
* INVALID_VALUE is generated if the width and height
* parameters are not equal."
*/
- ErrorInvalidValue("%s: for cube map, width must equal height", InfoFrom(func));
+ ErrorInvalidValue("%s: for cube map, width must equal height", InfoFrom(func, dims));
return false;
}
if (texImageTarget == LOCAL_GL_TEXTURE_2D || isCubemapTarget)
{
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "If wt and ht are the specified image width and height,
* and if either wt or ht are less than zero, then the error
* INVALID_VALUE is generated."
*/
if (width < 0) {
- ErrorInvalidValue("%s: width must be >= 0", InfoFrom(func));
+ ErrorInvalidValue("%s: width must be >= 0", InfoFrom(func, dims));
return false;
}
if (height < 0) {
- ErrorInvalidValue("%s: height must be >= 0", InfoFrom(func));
+ ErrorInvalidValue("%s: height must be >= 0", InfoFrom(func, dims));
return false;
}
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "The maximum allowable width and height of a
* two-dimensional texture image must be at least 2**(k−lod)
* for image arrays of level zero through k, where k is the
* log base 2 of MAX_TEXTURE_SIZE. and lod is the
* level-of-detail of the image array. It may be zero for
* image arrays of any level-of-detail greater than k. The
* error INVALID_VALUE is generated if the specified image
* is too large to be stored under any conditions.
*/
if (width > (int) maxTexImageSize) {
ErrorInvalidValue("%s: the maximum width for level %d is %u",
- InfoFrom(func), level, maxTexImageSize);
+ InfoFrom(func, dims), level, maxTexImageSize);
return false;
}
if (height > (int) maxTexImageSize) {
ErrorInvalidValue("%s: tex maximum height for level %d is %u",
- InfoFrom(func), level, maxTexImageSize);
+ InfoFrom(func, dims), level, maxTexImageSize);
return false;
}
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "If level is greater than zero, and either width or
* height is not a power-of-two, the error INVALID_VALUE is
* generated."
*/
if (level > 0) {
if (!is_pot_assuming_nonnegative(width)) {
ErrorInvalidValue("%s: level >= 0, width of %d must be a power of two.",
- InfoFrom(func), width);
+ InfoFrom(func, dims), width);
return false;
}
if (!is_pot_assuming_nonnegative(height)) {
ErrorInvalidValue("%s: level >= 0, height of %d must be a power of two.",
- InfoFrom(func), height);
+ InfoFrom(func, dims), height);
return false;
}
}
}
// TODO: WebGL 2
if (texImageTarget == LOCAL_GL_TEXTURE_3D) {
if (depth < 0) {
- ErrorInvalidValue("%s: depth must be >= 0", InfoFrom(func));
+ ErrorInvalidValue("%s: depth must be >= 0", InfoFrom(func, dims));
return false;
}
if (!is_pot_assuming_nonnegative(depth)) {
ErrorInvalidValue("%s: level >= 0, depth of %d must be a power of two.",
- InfoFrom(func), depth);
+ InfoFrom(func, dims), depth);
return false;
}
}
return true;
}
/**
* Validate texture image sizing for Tex(Sub)?Image variants.
*/
// TODO: WebGL 2. Update this to handle 3D textures.
bool
WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoffset*/,
GLsizei width, GLsizei height, GLsizei /*depth*/,
GLsizei baseWidth, GLsizei baseHeight, GLsizei /*baseDepth*/,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func, WebGLTexDimensions dims)
{
/* GL ES Version 2.0.25 - 3.7.1 Texture Image Specification
* "Taking wt and ht to be the specified width and height of the
* texture array, and taking x, y, w, and h to be the xoffset,
* yoffset, width, and height argument values, any of the
* following relationships generates the error INVALID_VALUE:
* x < 0
* x + w > wt
* y < 0
* y + h > ht"
*/
if (xoffset < 0) {
- ErrorInvalidValue("%s: xoffset must be >= 0", InfoFrom(func));
+ ErrorInvalidValue("%s: xoffset must be >= 0", InfoFrom(func, dims));
return false;
}
if (yoffset < 0) {
- ErrorInvalidValue("%s: yoffset must be >= 0", InfoFrom(func));
+ ErrorInvalidValue("%s: yoffset must be >= 0", InfoFrom(func, dims));
return false;
}
if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, baseWidth, baseHeight)) {
- ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func));
+ ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func, dims));
return false;
}
return true;
}
/**
* Perform validation of format/type combinations for TexImage variants.
* Returns true if the format/type is a valid combination, false otherwise.
*/
bool
WebGLContext::ValidateTexImageFormatAndType(GLenum format,
- GLenum type, WebGLTexImageFunc func)
+ GLenum type,
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
if (IsCompressedFunc(func) || IsCopyFunc(func))
{
MOZ_ASSERT(type == LOCAL_GL_NONE && format == LOCAL_GL_NONE);
return true;
}
- if (!ValidateTexImageFormat(format, func) ||
- !ValidateTexImageType(type, func))
+ if (!ValidateTexImageFormat(format, func, dims) ||
+ !ValidateTexImageType(type, func, dims))
{
return false;
}
// Here we're reinterpreting format as an unsized internalformat;
// these are the same in practice and there's no point in having the
// same code implemented twice.
TexInternalFormat effective =
EffectiveInternalFormatFromInternalFormatAndType(format, type);
bool validCombo = effective != LOCAL_GL_NONE;
if (!validCombo)
ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
- InfoFrom(func), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
+ InfoFrom(func, dims), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
return validCombo;
}
bool
WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
if (!IsCompressedTextureFormat(format)) {
ErrorInvalidEnum("%s: invalid compressed texture format: %s",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return false;
}
/* WEBGL_compressed_texture_atc added formats */
if (format == LOCAL_GL_ATC_RGB ||
format == LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA ||
format == LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA)
{
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_atc enabled",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
// WEBGL_compressed_texture_etc1
if (format == LOCAL_GL_ETC1_RGB8_OES) {
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_etc1 enabled",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
if (format == LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1 ||
format == LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1 ||
format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 ||
format == LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1)
{
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_pvrtc enabled",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
if (format == LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
format == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
{
bool validFormat = IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need WEBGL_compressed_texture_s3tc enabled",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
return validFormat;
}
return false;
}
bool
WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
bool valid = format == LOCAL_GL_RGBA ||
format == LOCAL_GL_RGB ||
format == LOCAL_GL_LUMINANCE_ALPHA ||
format == LOCAL_GL_LUMINANCE ||
format == LOCAL_GL_ALPHA;
if (!valid)
{
// in CopyTexImage, the internalformat is a function parameter,
// so a bad value is an INVALID_ENUM error.
// in CopyTexSubImage, the internalformat is part of existing state,
// so this is an INVALID_OPERATION error.
GenerateWarning("%s: invalid texture internal format: %s",
- InfoFrom(func), WebGLContext::EnumName(format));
+ InfoFrom(func, dims), WebGLContext::EnumName(format));
SynthesizeGLError(func == WebGLTexImageFunc::CopyTexImage
? LOCAL_GL_INVALID_ENUM
: LOCAL_GL_INVALID_OPERATION);
}
return valid;
}
/**
* Return true if format, type and jsArrayType are a valid combination.
* Also returns the size for texel of format and type (in bytes) via
* \a texelSize.
*
* It is assumed that type has previously been validated.
*/
bool
WebGLContext::ValidateTexInputData(GLenum type,
js::Scalar::Type jsArrayType,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
bool validInput = false;
const char invalidTypedArray[] = "%s: invalid typed array type for given texture data type";
// We're using js::Scalar::TypeMax as dummy value when the tex source wasn't a
// typed array.
if (jsArrayType == js::Scalar::TypeMax) {
return true;
@@ -1060,114 +1056,116 @@ WebGLContext::ValidateTexInputData(GLenu
validInput = jsArrayType == js::Scalar::Float32;
break;
default:
break;
}
if (!validInput)
- ErrorInvalidOperation(invalidTypedArray, InfoFrom(func));
+ ErrorInvalidOperation(invalidTypedArray, InfoFrom(func, dims));
return validInput;
}
/**
* Checks specific for the CopyTex[Sub]Image2D functions.
* Verifies:
* - Framebuffer is complete and has valid read planes
* - Copy format is a subset of framebuffer format (i.e. all required components are available)
*/
bool
WebGLContext::ValidateCopyTexImage(GLenum format,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
MOZ_ASSERT(IsCopyFunc(func));
// Default framebuffer format
GLenum fboFormat = bool(gl->GetPixelFormat().alpha > 0) ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
if (mBoundFramebuffer) {
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
- ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func));
+ ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", InfoFrom(func, dims));
return false;
}
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
ErrorInvalidOperation("%s: Read source attachment doesn't have the"
- " correct color/depth/stencil type.", InfoFrom(func));
+ " correct color/depth/stencil type.", InfoFrom(func, dims));
return false;
}
// Get the correct format for the framebuffer, as it's not the default one
const WebGLFramebuffer::Attachment& color0 = mBoundFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
fboFormat = mBoundFramebuffer->GetFormatForAttachment(color0);
}
// Make sure the format of the framebuffer is a superset of
// the format requested by the CopyTex[Sub]Image2D functions.
const GLComponents formatComps = GLComponents(format);
const GLComponents fboComps = GLComponents(fboFormat);
if (!formatComps.IsSubsetOf(fboComps)) {
ErrorInvalidOperation("%s: format %s is not a subset of the current framebuffer format, which is %s.",
- InfoFrom(func), EnumName(format), EnumName(fboFormat));
+ InfoFrom(func, dims), EnumName(format), EnumName(fboFormat));
return false;
}
return true;
}
/**
* Test the gl(Copy|Compressed)?Tex[Sub]?Image[23]() parameters for errors.
* Verifies each of the parameters against the WebGL standard and enabled extensions.
*/
// TODO: Texture dims is here for future expansion in WebGL 2.0
bool
-WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
+WebGLContext::ValidateTexImage(TexImageTarget texImageTarget,
GLint level,
GLenum internalFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format,
GLenum type,
- WebGLTexImageFunc func)
+ WebGLTexImageFunc func,
+ WebGLTexDimensions dims)
{
- const char* info = InfoFrom(func);
+ const char* info = InfoFrom(func, dims);
/* Check level */
if (level < 0) {
ErrorInvalidValue("%s: level must be >= 0", info);
return false;
}
/* Check border */
if (border != 0) {
ErrorInvalidValue("%s: border must be 0", info);
return false;
}
/* Check incoming image format and type */
- if (!ValidateTexImageFormatAndType(format, type, func))
+ if (!ValidateTexImageFormatAndType(format, type, func, dims))
return false;
if (!TexInternalFormat::IsValueLegal(internalFormat)) {
ErrorInvalidEnum("%s: invalid internalformat enum %s", info, EnumName(internalFormat));
return false;
}
TexInternalFormat unsizedInternalFormat =
UnsizedInternalFormatFromInternalFormat(internalFormat);
if (IsCompressedFunc(func)) {
- if (!ValidateCompTexImageInternalFormat(internalFormat, func)) {
+ if (!ValidateCompTexImageInternalFormat(internalFormat, func, dims)) {
return false;
}
} else if (IsCopyFunc(func)) {
- if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(), func)) {
+ if (!ValidateCopyTexImageInternalFormat(unsizedInternalFormat.get(), func, dims)) {
return false;
}
} else if (format != unsizedInternalFormat) {
if (IsWebGL2()) {
// In WebGL2, it's OK to have internalformat != format if internalformat is the sized
// internal format corresponding to the (format, type) pair according to Table 3.2
// in the OpenGL ES 3.0.3 spec.
if (internalFormat != EffectiveInternalFormatFromInternalFormatAndType(format, type)) {
@@ -1192,17 +1190,17 @@ WebGLContext::ValidateTexImage(GLuint di
} else {
// in WebGL 1, format must be equal to internalformat
ErrorInvalidOperation("%s: internalformat does not match format", info);
return false;
}
}
/* Check texture image size */
- if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func))
+ if (!ValidateTexImageSize(texImageTarget, level, width, height, 0, func, dims))
return false;
/* 5.14.8 Texture objects - WebGL Spec.
* "If an attempt is made to call these functions with no
* WebGLTexture bound (see above), an INVALID_OPERATION error
* is generated."
*/
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
@@ -1219,17 +1217,17 @@ WebGLContext::ValidateTexImage(GLuint di
return false;
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
width, height, depth,
imageInfo.Width(), imageInfo.Height(), 0,
- func))
+ func, dims))
{
return false;
}
}
/* Additional checks for depth textures */
if (texImageTarget != LOCAL_GL_TEXTURE_2D &&
(format == LOCAL_GL_DEPTH_COMPONENT ||
--- a/dom/canvas/WebGLTypes.h
+++ b/dom/canvas/WebGLTypes.h
@@ -41,66 +41,66 @@ namespace mozilla {
* with zero bytes, which means it's either opaque or transparent black
* depending on whether the image format has alpha.
*
* Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
* and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
*/
-MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, uint8_t)
Unknown,
NotNeeded,
Needed
MOZ_END_ENUM_CLASS(WebGLContextFakeBlackStatus)
-MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, uint8_t)
Unknown,
NotNeeded,
IncompleteTexture,
UninitializedImageData
MOZ_END_ENUM_CLASS(WebGLTextureFakeBlackStatus)
/*
* Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
* emulating the vertex attrib 0 array when it's not enabled. Indeed,
* OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
* desktop OpenGL does not allow that.
*/
-MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, uint8_t)
Default, // default status - no emulation needed
EmulatedUninitializedArray, // need an artificial attrib 0 array, but contents may be left uninitialized
EmulatedInitializedArray // need an artificial attrib 0 array, and contents must be initialized
MOZ_END_ENUM_CLASS(WebGLVertexAttrib0Status)
/*
* Enum to track the status of image data (renderbuffer or texture image) presence
* and initialization.
*
* - NoImageData is the initial state before any image data is allocated.
* - InitializedImageData is the state after image data is allocated and initialized.
* - UninitializedImageData is an intermediate state where data is allocated but not
* initialized. It is the state that renderbuffers are in after a renderbufferStorage call,
* and it is the state that texture images are in after a texImage2D call with null data.
*/
-MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, uint8_t)
NoImageData,
UninitializedImageData,
InitializedImageData
MOZ_END_ENUM_CLASS(WebGLImageDataStatus)
/*
* The formats that may participate, either as source or destination formats,
* in WebGL texture conversions. This includes:
* - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
* - additional formats provided by extensions, e.g. RGB32F
* - additional source formats, depending on browser details, used when uploading
* textures from DOM elements. See gfxImageSurface::Format().
*/
-MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, uint8_t)
// returned by SurfaceFromElementResultToImageSurface to indicate absence of image data
None,
// common value for formats for which format conversions are not supported
FormatNotSupportingAnyConversion,
// dummy pseudo-format meaning "use the other format".
// For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
// is implicitly treated as being RGB8 itself.
Auto,
@@ -125,25 +125,30 @@ MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, i
RGBA8,
BGRA8, // used for DOM elements
RGBA5551,
RGBA4444,
RGBA16F, // OES_texture_half_float
RGBA32F // OES_texture_float
MOZ_END_ENUM_CLASS(WebGLTexelFormat)
-MOZ_BEGIN_ENUM_CLASS(WebGLTexImageFunc, int)
+MOZ_BEGIN_ENUM_CLASS(WebGLTexImageFunc, uint8_t)
TexImage,
TexSubImage,
CopyTexImage,
CopyTexSubImage,
CompTexImage,
CompTexSubImage,
MOZ_END_ENUM_CLASS(WebGLTexImageFunc)
+MOZ_BEGIN_ENUM_CLASS(WebGLTexDimensions, uint8_t)
+ Tex2D,
+ Tex3D
+MOZ_END_ENUM_CLASS(WebGLTexDimensions)
+
// Please keep extensions in alphabetic order.
MOZ_BEGIN_ENUM_CLASS(WebGLExtensionID, uint8_t)
ANGLE_instanced_arrays,
EXT_blend_minmax,
EXT_color_buffer_half_float,
EXT_frag_depth,
EXT_sRGB,
EXT_shader_texture_lod,