--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -12,16 +12,17 @@
#include "mozilla/LinkedList.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "GLDefs.h"
#include "WebGLActiveInfo.h"
#include "WebGLObjectModel.h"
#include "WebGLRenderbuffer.h"
+#include "WebGLTexture.h"
#include "WebGLStrongTypes.h"
#include <stdarg.h>
#include "nsTArray.h"
#include "nsCycleCollectionNoteChild.h"
#include "nsIDOMWebGLRenderingContext.h"
#include "nsICanvasRenderingContextInternal.h"
@@ -216,16 +217,17 @@ public:
/**
* Return displayable name for GLenum.
* This version is like gl::GLenumToStr but with out the GL_ prefix to
* keep consistency with how errors are reported from WebGL.
*/
static const char *EnumName(GLenum glenum);
+ bool IsCompressedTextureFormat(GLenum format);
bool IsTextureFormatCompressed(TexInternalFormat format);
void DummyFramebufferOperation(const char *info);
WebGLTexture* activeBoundTextureForTarget(const TexTarget texTarget) const {
return texTarget == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
: mBoundCubeMapTextures[mActiveTexture];
}
@@ -538,19 +540,22 @@ public:
const Nullable<dom::ArrayBufferView> &pixels,
ErrorResult& rv);
void TexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLenum format,
GLenum type, dom::ImageData* pixels, ErrorResult& rv);
// Allow whatever element types the bindings are willing to pass
// us in TexSubImage2D
template<class ElementType>
- void TexSubImage2D(GLenum rawTexImageTarget, GLint level,
- GLint xoffset, GLint yoffset, GLenum format,
- GLenum type, ElementType& elt, ErrorResult& rv)
+ void TexSubImage2D(GLenum rawTexImageTarget,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLenum format,
+ GLenum type,
+ ElementType& elt, ErrorResult& rv)
{
if (IsContextLost())
return;
if (!ValidateTexImageTarget(2, rawTexImageTarget, WebGLTexImageFunc::TexSubImage))
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
const TexImageTarget texImageTarget(rawTexImageTarget);
@@ -560,32 +565,41 @@ public:
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel)
return ErrorInvalidValue("texSubImage2D: level %d is too large, max is %d", level, maxLevel);
+ WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
+ if (!tex) {
+ return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
+ }
+ const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(texImageTarget, level);
+ const TexInternalFormat internalformat = imageInfo.InternalFormat();
+
// Trying to handle the video by GPU directly first
- if (TexImageFromVideoElement(texImageTarget, level, format, format, type, elt)) {
+ if (TexImageFromVideoElement(texImageTarget, level,
+ internalformat.get(), format, type, elt))
+ {
return;
}
RefPtr<gfx::DataSourceSurface> data;
WebGLTexelFormat srcFormat;
nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
rv = SurfaceFromElementResultToImageSurface(res, data,
&srcFormat);
if (rv.Failed() || !data)
return;
gfx::IntSize size = data->GetSize();
uint32_t byteLength = data->Stride() * size.height;
- return TexSubImage2D_base(texImageTarget, level, xoffset, yoffset,
+ return TexSubImage2D_base(texImageTarget.get(), level, xoffset, yoffset,
size.width, size.height,
data->Stride(), format, type,
data->GetData(), byteLength,
-1, srcFormat, mPixelStorePremultiplyAlpha);
}
void Uniform1i(WebGLUniformLocation* location, GLint x);
@@ -1068,17 +1082,17 @@ protected:
virtual bool IsWebGL2() const = 0;
bool InitWebGL2();
// -------------------------------------------------------------------------
// Validation functions (implemented in WebGLContextValidate.cpp)
- TexFormat BaseTexFormat(TexInternalFormat internalFormat) const;
+ TexInternalFormat BaseTexFormat(TexInternalFormat internalFormat) const;
bool CreateOffscreenGL(bool forceEnabled);
bool InitAndValidateGL();
bool ResizeBackbuffer(uint32_t width, uint32_t height);
bool ValidateBlendEquationEnum(GLenum cap, const char *info);
bool ValidateBlendFuncDstEnum(GLenum mode, const char *info);
bool ValidateBlendFuncSrcEnum(GLenum mode, const char *info);
bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor, const char *info);
@@ -1090,63 +1104,74 @@ protected:
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 format, WebGLTexImageFunc func);
+ bool ValidateCopyTexImage(GLenum internalformat,
+ WebGLTexImageFunc func);
bool ValidateTexImage(GLuint dims, 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);
- bool ValidateTexImageFormat(GLenum format, WebGLTexImageFunc func);
+ bool ValidateTexImageFormat(GLenum internalformat,
+ WebGLTexImageFunc func);
bool ValidateTexImageType(GLenum type, WebGLTexImageFunc func);
bool ValidateTexImageFormatAndType(GLenum format, GLenum type, WebGLTexImageFunc func);
+ bool ValidateCompTexImageInternalFormat(GLenum format,
+ WebGLTexImageFunc func);
+ bool ValidateCopyTexImageInternalFormat(GLenum format,
+ WebGLTexImageFunc func);
bool ValidateTexImageSize(TexImageTarget target, GLint level,
GLint width, GLint height, GLint depth,
WebGLTexImageFunc func);
bool ValidateTexSubImageSize(GLint x, GLint y, GLint z,
GLsizei width, GLsizei height, GLsizei depth,
GLsizei baseWidth, GLsizei baseHeight, GLsizei baseDepth,
WebGLTexImageFunc func);
- bool ValidateCompTexImageSize(GLint level, GLenum format,
+ bool ValidateCompTexImageSize(GLint level,
+ GLenum internalformat,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
WebGLTexImageFunc func);
- bool ValidateCompTexImageDataSize(GLint level, GLenum format,
+ bool ValidateCompTexImageDataSize(GLint level,
+ GLenum internalformat,
GLsizei width, GLsizei height,
uint32_t byteLength, WebGLTexImageFunc func);
-
static uint32_t GetBitsPerTexel(TexInternalFormat format, TexType type);
void Invalidate();
void DestroyResourcesAndContext();
void MakeContextCurrent() const;
// helpers
- void TexImage2D_base(TexImageTarget target, GLint level, GLenum internalformat,
+ void TexImage2D_base(TexImageTarget target,
+ GLint level,
+ GLenum internalformat,
GLsizei width, GLsizei height, GLsizei srcStrideOrZero, GLint border,
- GLenum format, GLenum type,
+ GLenum format,
+ GLenum type,
void *data, uint32_t byteLength,
int jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexSubImage2D_base(TexImageTarget target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
- GLenum format, GLenum type,
+ GLenum format,
+ GLenum type,
void *pixels, uint32_t byteLength,
int jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied);
void TexParameter_base(GLenum target, GLenum pname,
GLint *intParamPtr, GLfloat *floatParamPtr);
void ConvertImage(size_t width, size_t height, size_t srcStride, size_t dstStride,
const uint8_t* src, uint8_t *dst,
@@ -1222,22 +1247,22 @@ protected:
GLenum CheckedBufferData(GLenum target,
GLsizeiptr size,
const GLvoid *data,
GLenum usage);
/** like glTexImage2D but if the call may change the texture size, checks any GL error generated
* by this glTexImage2D call and returns it */
GLenum CheckedTexImage2D(TexImageTarget texImageTarget,
GLint level,
- GLenum internalFormat,
+ TexInternalFormat internalFormat,
GLsizei width,
GLsizei height,
GLint border,
- GLenum format,
- GLenum type,
+ TexFormat format,
+ TexType type,
const GLvoid *data);
void ForceLoseContext(bool simulateLosing = false);
void ForceRestoreContext();
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -370,17 +370,18 @@ WebGLContext::CopyTexSubImage2D_base(Tex
const char* info = sub ? "copyTexSubImage2D" : "copyTexImage2D";
WebGLTexImageFunc func = sub ? WebGLTexImageFunc::CopyTexSubImage : WebGLTexImageFunc::CopyTexImage;
// TODO: This changes with color_buffer_float. Reassess when the
// patch lands.
if (!ValidateTexImage(2, texImageTarget, level, internalformat,
xoffset, yoffset, 0,
width, height, 0,
- 0, internalformat, LOCAL_GL_UNSIGNED_BYTE,
+ 0,
+ LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
{
return;
}
if (!ValidateCopyTexImage(internalformat, func))
return;
@@ -473,65 +474,65 @@ WebGLContext::CopyTexImage2D(GLenum rawT
GLsizei height,
GLint border)
{
if (IsContextLost())
return;
// copyTexImage2D only generates textures with type = UNSIGNED_BYTE
const WebGLTexImageFunc func = WebGLTexImageFunc::CopyTexImage;
- const GLenum format = internalformat; // WebGL/ES Format
- const GLenum type = LOCAL_GL_UNSIGNED_BYTE; // WebGL/ES Format
if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CopyTexImage))
return;
- if (!ValidateTexImage(2, rawTexImgTarget, level, format,
+ if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
0, 0, 0,
width, height, 0,
- border, format, type,
+ border, LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
{
return;
}
- if (!ValidateCopyTexImage(format, func))
+ if (!ValidateCopyTexImage(internalformat, func))
return;
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
const TexImageTarget texImageTarget(rawTexImgTarget);
// check if the memory size of this texture may change with this call
bool sizeMayChange = true;
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
if (tex->HasImageInfoAt(texImageTarget, level)) {
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
sizeMayChange = width != imageInfo.Width() ||
height != imageInfo.Height() ||
- internalformat != imageInfo.InternalFormat() ||
- type != imageInfo.Type();
+ internalformat != imageInfo.InternalFormat();
}
if (sizeMayChange)
GetAndFlushUnderlyingGLErrors();
- CopyTexSubImage2D_base(texImageTarget, level, format, 0, 0, x, y, width, height, false);
+ CopyTexSubImage2D_base(texImageTarget, level, internalformat, 0, 0, x, y, width, height, false);
if (sizeMayChange) {
GLenum error = GetAndFlushUnderlyingGLErrors();
if (error) {
GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
return;
}
}
- tex->SetImageInfo(texImageTarget, level, width, height, internalformat, type,
+ tex->SetImageInfo(texImageTarget, level, width, height,
+ internalformat,
+ LOCAL_GL_UNSIGNED_BYTE, /* dummy, artifact of us storing
+ the wrong data in ImageInfo */
WebGLImageDataStatus::InitializedImageData);
}
void
WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
GLint level,
GLint xoffset,
GLint yoffset,
@@ -573,17 +574,17 @@ WebGLContext::CopyTexSubImage2D(GLenum r
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
if (!tex)
return ErrorInvalidOperation("copyTexSubImage2D: no texture bound to this target");
if (!tex->HasImageInfoAt(texImageTarget, level))
return ErrorInvalidOperation("copyTexSubImage2D: no texture image previously defined for this level and face");
- const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(texImageTarget, level);
+ const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
GLsizei texWidth = imageInfo.Width();
GLsizei texHeight = imageInfo.Height();
if (xoffset + width > texWidth || xoffset + width < 0)
return ErrorInvalidValue("copyTexSubImage2D: xoffset+width is too large");
if (yoffset + height > texHeight || yoffset + height < 0)
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
@@ -3293,31 +3294,34 @@ WebGLContext::CompileShader(WebGLShader
gl->fCompileShader(shadername);
GLint ok;
gl->fGetShaderiv(shadername, LOCAL_GL_COMPILE_STATUS, &ok);
shader->SetCompileStatus(ok);
}
void
-WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget, GLint level, GLenum internalformat,
+WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
+ GLint level,
+ 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))
return;
if (!ValidateTexImage(2, rawTexImgTarget, level, internalformat,
0, 0, 0, width, height, 0,
- border, internalformat, LOCAL_GL_UNSIGNED_BYTE,
+ border, LOCAL_GL_NONE,
+ LOCAL_GL_NONE,
func))
{
return;
}
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
@@ -3338,62 +3342,67 @@ WebGLContext::CompressedTexImage2D(GLenu
MOZ_ASSERT(tex);
tex->SetImageInfo(texImageTarget, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
WebGLImageDataStatus::InitializedImageData);
}
void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint xoffset,
GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, const ArrayBufferView& view)
+ GLenum internalformat,
+ const ArrayBufferView& view)
{
if (IsContextLost())
return;
const WebGLTexImageFunc func = WebGLTexImageFunc::CompTexSubImage;
if (!ValidateTexImageTarget(2, rawTexImgTarget, WebGLTexImageFunc::CompTexSubImage))
return;
if (!ValidateTexImage(2, rawTexImgTarget,
- level, format,
+ level, internalformat,
xoffset, yoffset, 0,
width, height, 0,
- 0, format, LOCAL_GL_UNSIGNED_BYTE,
+ 0, LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
{
return;
}
const TexImageTarget texImageTarget(rawTexImgTarget);
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex);
WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(texImageTarget, level);
+ if (internalformat != levelInfo.InternalFormat()) {
+ return ErrorInvalidOperation("compressedTexImage2D: internalformat does not match the existing image");
+ }
+
view.ComputeLengthAndData();
uint32_t byteLength = view.Length();
- if (!ValidateCompTexImageDataSize(level, format, width, height, byteLength, func))
+ if (!ValidateCompTexImageDataSize(level, internalformat, width, height, byteLength, func))
return;
- if (!ValidateCompTexImageSize(level, format,
+ if (!ValidateCompTexImageSize(level, internalformat,
xoffset, yoffset,
width, height,
levelInfo.Width(), levelInfo.Height(),
func))
{
return;
}
if (levelInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
MakeContextCurrent();
- gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, width, height, format, byteLength, view.Data());
+ gl->fCompressedTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, width, height, internalformat, byteLength, view.Data());
}
JS::Value
WebGLContext::GetShaderParameter(WebGLShader *shader, GLenum pname)
{
if (IsContextLost())
return JS::NullValue();
@@ -3572,63 +3581,63 @@ WebGLContext::GetShaderTranslatedSource(
if (!ValidateObject("getShaderTranslatedSource: shader", shader))
return;
retval.Assign(shader->TranslatedSource());
}
GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget,
GLint level,
- GLenum internalFormat,
+ TexInternalFormat internalFormat,
GLsizei width,
GLsizei height,
GLint border,
- GLenum format,
- GLenum type,
+ TexFormat format,
+ TexType type,
const GLvoid *data)
{
- MOZ_ASSERT(internalFormat == format);
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex != nullptr, "no texture bound");
bool sizeMayChange = true;
if (tex->HasImageInfoAt(texImageTarget, level)) {
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
sizeMayChange = width != imageInfo.Width() ||
height != imageInfo.Height() ||
- format != imageInfo.InternalFormat() ||
- type != imageInfo.Type();
+ internalFormat != imageInfo.InternalFormat();
}
// Convert to format and type required by OpenGL 'driver'.
GLenum driverType = DriverTypeFromType(gl, type);
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
- DriverFormatsFromFormatAndType(gl, format, type, &driverInternalFormat, &driverFormat);
+ DriverFormatsFromFormatAndType(gl, internalFormat, type, &driverInternalFormat, &driverFormat);
if (sizeMayChange) {
GetAndFlushUnderlyingGLErrors();
}
gl->fTexImage2D(texImageTarget.get(), level, driverInternalFormat, width, height, border, driverFormat, driverType, data);
GLenum error = LOCAL_GL_NO_ERROR;
if (sizeMayChange) {
error = GetAndFlushUnderlyingGLErrors();
}
return error;
}
void
-WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level, GLenum internalformat,
+WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
+ GLenum internalformat,
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
GLint border,
- GLenum format, GLenum type,
+ GLenum format,
+ GLenum type,
void* data, uint32_t byteLength,
int jsArrayType, // a TypedArray format enum, or -1 if not relevant
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
if (!ValidateTexImage(2, texImageTarget, level, internalformat,
0, 0, 0,
@@ -3647,17 +3656,17 @@ WebGLContext::TexImage2D_base(TexImageTa
"with format of DEPTH_COMPONENT or DEPTH_STENCIL, "
"data must be nullptr, "
"level must be zero");
}
if (!ValidateTexInputData(type, jsArrayType, func))
return;
- WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
+ WebGLTexelFormat dstFormat = GetWebGLTexelFormat(internalformat, type);
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
CheckedUint32 checked_neededByteLength =
GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
@@ -3681,17 +3690,17 @@ WebGLContext::TexImage2D_base(TexImageTa
MakeContextCurrent();
nsAutoArrayPtr<uint8_t> convertedData;
void* pixels = nullptr;
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
if (byteLength) {
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
- uint32_t dstTexelSize = GetBitsPerTexel(format, type) / 8;
+ uint32_t dstTexelSize = GetBitsPerTexel(internalformat, type) / 8;
size_t dstPlainRowSize = dstTexelSize * width;
size_t unpackAlignment = mPixelStoreUnpackAlignment;
size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
if (actualSrcFormat == dstFormat &&
srcPremultiplied == mPixelStorePremultiplyAlpha &&
srcStride == dstStride &&
!mPixelStoreFlipY)
@@ -3798,28 +3807,39 @@ WebGLContext::TexSubImage2D_base(TexImag
GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
GLenum format, GLenum type,
void* data, uint32_t byteLength,
int jsArrayType,
WebGLTexelFormat srcFormat, bool srcPremultiplied)
{
const WebGLTexImageFunc func = WebGLTexImageFunc::TexSubImage;
- if (!ValidateTexImage(2, texImageTarget, level, format,
+ WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
+ if (!tex) {
+ return ErrorInvalidOperation("texSubImage2D: no texture bound on active texture unit");
+ }
+ const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
+ const TexInternalFormat internalformat = imageInfo.InternalFormat();
+
+ if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
xoffset, yoffset, 0,
width, height, 0,
0, format, type, func))
{
return;
}
if (!ValidateTexInputData(type, jsArrayType, func))
return;
- WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
+ if (imageInfo.Type() != type) {
+ return ErrorInvalidOperation("texSubImage2D: type parameter does not match the existing image");
+ }
+
+ WebGLTexelFormat dstFormat = GetWebGLTexelFormat(internalformat, type);
WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
if (width == 0 || height == 0)
return; // ES 2.0 says it has no effect, we better return right now
CheckedUint32 checked_neededByteLength =
@@ -3833,26 +3853,23 @@ WebGLContext::TexSubImage2D_base(TexImag
if (!checked_neededByteLength.isValid())
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
uint32_t bytesNeeded = checked_neededByteLength.value();
if (byteLength < bytesNeeded)
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
- WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
- const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(texImageTarget, level);
-
if (imageInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
MakeContextCurrent();
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
- uint32_t dstTexelSize = GetBitsPerTexel(format, type) / 8;
+ uint32_t dstTexelSize = GetBitsPerTexel(internalformat, type) / 8;
size_t dstPlainRowSize = dstTexelSize * width;
// There are checks above to ensure that this won't overflow.
size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
void* pixels = data;
nsAutoArrayPtr<uint8_t> convertedData;
// no conversion, no flipping, so we avoid copying anything and just pass the source pointer
@@ -3869,17 +3886,17 @@ WebGLContext::TexSubImage2D_base(TexImag
actualSrcFormat, srcPremultiplied,
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
pixels = reinterpret_cast<void*>(convertedData.get());
}
GLenum driverType = DriverTypeFromType(gl, type);
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
- DriverFormatsFromFormatAndType(gl, format, type, &driverInternalFormat, &driverFormat);
+ DriverFormatsFromFormatAndType(gl, internalformat, type, &driverInternalFormat, &driverFormat);
gl->fTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, width, height, driverFormat, driverType, pixels);
}
void
WebGLContext::TexSubImage2D(GLenum rawTarget, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -485,21 +485,20 @@ WebGLContext::EnumName(GLenum glenum)
XX(UNSIGNED_SHORT_5_5_5_1);
XX(UNSIGNED_SHORT_5_6_5);
#undef XX
}
return "[Unknown enum name]";
}
-
bool
-WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
+WebGLContext::IsCompressedTextureFormat(GLenum format)
{
- switch (format.get()) {
+ switch (format) {
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:
case LOCAL_GL_ATC_RGB:
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
@@ -508,16 +507,23 @@ WebGLContext::IsTextureFormatCompressed(
case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
case LOCAL_GL_ETC1_RGB8_OES:
return true;
default:
return false;
}
}
+
+bool
+WebGLContext::IsTextureFormatCompressed(TexInternalFormat format)
+{
+ return IsCompressedTextureFormat(format.get());
+}
+
GLenum
WebGLContext::GetAndFlushUnderlyingGLErrors()
{
// Get and clear GL error in ALL cases.
GLenum error = gl->GetAndClearError();
// Only store in mUnderlyingGLError if is hasn't already recorded an
// error.
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -77,16 +77,23 @@ InfoFrom(WebGLTexImageFunc func)
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)
{
const char* name = WebGLContext::EnumName(glenum);
@@ -243,90 +250,90 @@ WebGLProgram::UpdateInfo()
}
/**
* Return the simple base format for a given internal format.
*
* \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
* GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA), or GL_NONE if invalid enum.
*/
-TexFormat
+TexInternalFormat
WebGLContext::BaseTexFormat(TexInternalFormat internalFormat) const
{
if (internalFormat == LOCAL_GL_ALPHA ||
internalFormat == LOCAL_GL_LUMINANCE ||
internalFormat == LOCAL_GL_LUMINANCE_ALPHA ||
internalFormat == LOCAL_GL_RGB ||
internalFormat == LOCAL_GL_RGBA)
{
- return TexFormat(internalFormat.get());
+ return internalFormat;
}
if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
if (internalFormat == LOCAL_GL_SRGB)
- return TexFormat(LOCAL_GL_RGB);
+ return LOCAL_GL_RGB;
if (internalFormat == LOCAL_GL_SRGB_ALPHA)
- return TexFormat(LOCAL_GL_RGBA);
+ return LOCAL_GL_RGBA;
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_atc)) {
if (internalFormat == LOCAL_GL_ATC_RGB)
- return TexFormat(LOCAL_GL_RGB);
+ return LOCAL_GL_RGB;
if (internalFormat == LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA ||
internalFormat == LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA)
{
- return TexFormat(LOCAL_GL_RGBA);
+ return LOCAL_GL_RGBA;
}
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_etc1)) {
if (internalFormat == LOCAL_GL_ETC1_RGB8_OES)
- return TexFormat(LOCAL_GL_RGB);
+ return LOCAL_GL_RGB;
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_pvrtc)) {
if (internalFormat == LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1 ||
internalFormat == LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1)
{
- return TexFormat(LOCAL_GL_RGB);
+ return LOCAL_GL_RGB;
}
if (internalFormat == LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1 ||
internalFormat == LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1)
{
- return TexFormat(LOCAL_GL_RGBA);
+ return LOCAL_GL_RGBA;
}
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_compressed_texture_s3tc)) {
if (internalFormat == LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
- return TexFormat(LOCAL_GL_RGB);
+ return LOCAL_GL_RGB;
if (internalFormat == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ||
internalFormat == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ||
internalFormat == LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
{
- return TexFormat(LOCAL_GL_RGBA);
+ return LOCAL_GL_RGBA;
}
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture)) {
if (internalFormat == LOCAL_GL_DEPTH_COMPONENT ||
internalFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
internalFormat == LOCAL_GL_DEPTH_COMPONENT32)
{
- return TexFormat(LOCAL_GL_DEPTH_COMPONENT);
+ return LOCAL_GL_DEPTH_COMPONENT;
}
if (internalFormat == LOCAL_GL_DEPTH_STENCIL ||
internalFormat == LOCAL_GL_DEPTH24_STENCIL8)
{
- return TexFormat(LOCAL_GL_DEPTH_STENCIL);
+ return LOCAL_GL_DEPTH_STENCIL;
}
}
MOZ_ASSERT(false, "Unhandled internalFormat");
return LOCAL_GL_NONE;
}
bool WebGLContext::ValidateBlendEquationEnum(GLenum mode, const char *info)
@@ -603,73 +610,28 @@ WebGLContext::ValidateTexImageFormat(GLe
{
bool validFormat = IsExtensionEnabled(WebGLExtensionID::EXT_sRGB);
if (!validFormat)
ErrorInvalidEnum("%s: invalid format %s: need EXT_sRGB enabled",
InfoFrom(func), WebGLContext::EnumName(format));
return validFormat;
}
- /* 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));
- 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));
- 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));
- 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));
- return validFormat;
- }
-
ErrorInvalidEnumWithName(this, "invalid format", format, func);
return false;
}
/**
* Check if the given texture target is valid for TexImage.
*/
bool
-WebGLContext::ValidateTexImageTarget(GLuint dims, GLenum target, WebGLTexImageFunc func)
+WebGLContext::ValidateTexImageTarget(GLuint dims,
+ GLenum target,
+ WebGLTexImageFunc func)
{
switch (dims) {
case 2:
if (target == LOCAL_GL_TEXTURE_2D ||
IsTexImageCubemapTarget(target))
{
return true;
}
@@ -684,17 +646,18 @@ WebGLContext::ValidateTexImageTarget(GLu
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)
+WebGLContext::ValidateTexImageType(GLenum type,
+ WebGLTexImageFunc func)
{
/* 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;
@@ -735,17 +698,18 @@ WebGLContext::ValidateTexImageType(GLenu
}
/**
* Validate texture image sizing extra constraints for
* CompressedTex(Sub)?Image.
*/
// TODO: WebGL 2
bool
-WebGLContext::ValidateCompTexImageSize(GLint level, GLenum format,
+WebGLContext::ValidateCompTexImageSize(GLint level,
+ GLenum format,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
WebGLTexImageFunc func)
{
// Negative parameters must already have been handled above
MOZ_ASSERT(xoffset >= 0 && yoffset >= 0 &&
width >= 0 && height >= 0);
@@ -1150,18 +1114,24 @@ WebGLContext::GetBitsPerTexel(TexInterna
return 0;
}
/**
* 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)
+WebGLContext::ValidateTexImageFormatAndType(GLenum format,
+ GLenum type, WebGLTexImageFunc func)
{
+ if (IsCompressedFunc(func) || IsCopyFunc(func))
+ {
+ MOZ_ASSERT(type == LOCAL_GL_NONE && format == LOCAL_GL_NONE);
+ return true;
+ }
if (!ValidateTexImageFormat(format, func) ||
!ValidateTexImageType(type, func))
{
return false;
}
bool validCombo = false;
@@ -1198,46 +1168,114 @@ WebGLContext::ValidateTexImageFormatAndT
validCombo = (type == LOCAL_GL_UNSIGNED_SHORT ||
type == LOCAL_GL_UNSIGNED_INT);
break;
case LOCAL_GL_DEPTH_STENCIL:
validCombo = (type == LOCAL_GL_UNSIGNED_INT_24_8);
break;
- case LOCAL_GL_ATC_RGB:
- case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
- case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
- case LOCAL_GL_ETC1_RGB8_OES:
- case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
- case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
- case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
- case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
- 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:
- validCombo = (type == LOCAL_GL_UNSIGNED_BYTE);
- break;
-
default:
// Only valid formats should be passed to the switch stmt.
MOZ_ASSERT(false, "Unexpected format and type combo. How'd this happen?");
validCombo = false;
// Fall through to return an InvalidOperations. This will alert us to the
// unexpected case that needs fixing in builds without asserts.
}
if (!validCombo)
ErrorInvalidOperation("%s: invalid combination of format %s and type %s",
InfoFrom(func), WebGLContext::EnumName(format), WebGLContext::EnumName(type));
return validCombo;
}
+bool
+WebGLContext::ValidateCompTexImageInternalFormat(GLenum format,
+ WebGLTexImageFunc func)
+{
+ if (!IsCompressedTextureFormat(format)) {
+ ErrorInvalidEnum("%s: invalid compressed texture format: %s",
+ InfoFrom(func), 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));
+ 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));
+ 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));
+ 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));
+ return validFormat;
+ }
+
+ return false;
+}
+
+bool
+WebGLContext::ValidateCopyTexImageInternalFormat(GLenum format,
+ WebGLTexImageFunc func)
+{
+ 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));
+ 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
@@ -1282,17 +1320,18 @@ WebGLContext::ValidateTexInputData(GLenu
/**
* 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)
+WebGLContext::ValidateCopyTexImage(GLenum format,
+ WebGLTexImageFunc func)
{
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()) {
@@ -1327,20 +1366,23 @@ WebGLContext::ValidateCopyTexImage(GLenu
/**
* 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,
- GLint level, GLenum internalFormat,
+ GLint level,
+ GLenum internalFormat,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
- GLint border, GLenum format, GLenum type,
+ GLint border,
+ GLenum format,
+ GLenum type,
WebGLTexImageFunc func)
{
const char* info = InfoFrom(func);
/* Check level */
if (level < 0) {
ErrorInvalidValue("%s: level must be >= 0", info);
return false;
@@ -1351,23 +1393,31 @@ WebGLContext::ValidateTexImage(GLuint di
ErrorInvalidValue("%s: border must be 0", info);
return false;
}
/* Check incoming image format and type */
if (!ValidateTexImageFormatAndType(format, type, func))
return false;
- /* WebGL and OpenGL ES 2.0 impose additional restrictions on the
- * combinations of format, internalFormat, and type that can be
- * used. Formats and types that require additional extensions
- * (e.g., GL_FLOAT requires GL_OES_texture_float) are filtered
- * elsewhere.
- */
- if (format != internalFormat) {
+ if (IsCompressedFunc(func)) {
+ if (!ValidateCompTexImageInternalFormat(internalFormat, func)) {
+ return false;
+ }
+ } else if (IsCopyFunc(func)) {
+ if (!ValidateCopyTexImageInternalFormat(internalFormat, func)) {
+ return false;
+ }
+ } else if (format != internalFormat) {
+ /* WebGL and OpenGL ES 2.0 impose additional restrictions on the
+ * combinations of format, internalFormat, and type that can be
+ * used. Formats and types that require additional extensions
+ * (e.g., GL_FLOAT requires GL_OES_texture_float) are filtered
+ * elsewhere.
+ */
ErrorInvalidOperation("%s: format does not match internalformat", info);
return false;
}
/* check internalFormat */
// TODO: Not sure if this is a bit of over kill.
if (BaseTexFormat(internalFormat) == LOCAL_GL_NONE) {
MOZ_ASSERT(false);
@@ -1401,41 +1451,30 @@ WebGLContext::ValidateTexImage(GLuint di
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
width, height, depth,
imageInfo.Width(), imageInfo.Height(), 0,
func))
{
return false;
}
-
- /* Require the format and type to match that of the existing
- * texture as created
- */
- if (imageInfo.InternalFormat() != internalFormat ||
- imageInfo.Type() != type)
- {
- ErrorInvalidOperation("%s: format or type doesn't match the existing texture",
- info);
- return false;
- }
}
/* Additional checks for depth textures */
if (texImageTarget != LOCAL_GL_TEXTURE_2D &&
(format == LOCAL_GL_DEPTH_COMPONENT ||
format == LOCAL_GL_DEPTH_STENCIL))
{
ErrorInvalidOperation("%s: with format of %s target must be TEXTURE_2D",
info, WebGLContext::EnumName(format));
return false;
}
/* Additional checks for compressed textures */
- if (!IsAllowedFromSource(format, func)) {
+ if (!IsAllowedFromSource(internalFormat, func)) {
ErrorInvalidOperation("%s: Invalid format %s for this operation",
info, WebGLContext::EnumName(format));
return false;
}
/* Parameters are OK */
return true;
}