--- a/dom/canvas/WebGL2ContextTextures.cpp
+++ b/dom/canvas/WebGL2ContextTextures.cpp
@@ -148,26 +148,19 @@ WebGL2Context::TexStorage2D(GLenum targe
WebGLTexture* tex = activeBoundTextureForTarget(target);
tex->SetImmutable();
const size_t facesCount = (target == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
GLsizei w = width;
GLsizei h = height;
for (size_t l = 0; l < size_t(levels); l++) {
for (size_t f = 0; f < facesCount; f++) {
- TexImageTarget imageTarget = TexImageTargetForTargetAndFace(target, f);
- // FIXME: SetImageInfo wants a type, to go with the internalformat that it stores.
- // 'type' is deprecated by sized internalformats, which are how TexStorage works.
- // We must fix WebGLTexture::ImageInfo to store an "effective internalformat",
- // which in the present case is just the sized internalformat, and drop 'types'
- // altogether. For now, we just pass LOCAL_GL_UNSIGNED_BYTE, which works For
- // the most commonly used formats.
- const GLenum type = LOCAL_GL_UNSIGNED_BYTE;
- tex->SetImageInfo(imageTarget, l, w, h,
- internalformat, type,
+ tex->SetImageInfo(TexImageTargetForTargetAndFace(target, f),
+ l, w, h,
+ internalformat,
WebGLImageDataStatus::UninitializedImageData);
}
w = std::max(1, w/2);
h = std::max(1, h/2);
}
gl->fTexStorage2D(target, levels, internalformat, width, height);
}
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1755,16 +1755,23 @@ WebGLContext::DidRefresh()
gl->FlushIfHeavyGLCallsSinceLastFlush();
}
}
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))
+ return false;
+
HTMLVideoElement* video = HTMLVideoElement::FromContentOrNull(&elt);
if (!video) {
return false;
}
uint16_t readyState;
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA)
@@ -1802,18 +1809,21 @@ bool WebGLContext::TexImageFromVideoElem
bool dimensionsMatch = info.Width() == srcImage->GetSize().width &&
info.Height() == srcImage->GetSize().height;
if (!dimensionsMatch) {
// we need to allocation
gl->fTexImage2D(texImageTarget.get(), level, internalformat, srcImage->GetSize().width, srcImage->GetSize().height, 0, format, type, nullptr);
}
bool ok = gl->BlitHelper()->BlitImageToTexture(srcImage.get(), srcImage->GetSize(), tex->GLName(), texImageTarget.get(), mPixelStoreFlipY);
if (ok) {
- tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height, internalformat, type,
- WebGLImageDataStatus::InitializedImageData);
+ TexInternalFormat effectiveinternalformat =
+ EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
+ MOZ_ASSERT(effectiveinternalformat != LOCAL_GL_NONE);
+ tex->SetImageInfo(texImageTarget, level, srcImage->GetSize().width, srcImage->GetSize().height,
+ effectiveinternalformat, WebGLImageDataStatus::InitializedImageData);
tex->Bind(TexImageTargetToTexTarget(texImageTarget));
}
srcImage = nullptr;
container->UnlockCurrentImage();
return ok;
}
////////////////////////////////////////////////////////////////////////////////
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -89,17 +89,17 @@ class Element;
struct WebGLContextAttributes;
template<typename> struct Nullable;
}
namespace gfx {
class SourceSurface;
}
-WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format, TexType type);
+WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
struct WebGLContextOptions {
// these are defaults
WebGLContextOptions();
bool operator==(const WebGLContextOptions& other) const {
@@ -485,19 +485,16 @@ public:
auto dims = 2;
if (!ValidateTexImageTarget(dims, rawTexImgTarget, WebGLTexImageFunc::TexImage))
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImgTarget);
const TexImageTarget texImageTarget(rawTexImgTarget);
- if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
- return;
-
if (level < 0)
return ErrorInvalidValue("texImage2D: level is negative");
const int32_t maxLevel = MaxTextureLevelForTexImageTarget(texImageTarget);
if (level > maxLevel)
return ErrorInvalidValue("texImage2D: level %d is too large, max is %d", level, maxLevel);
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
@@ -555,32 +552,29 @@ public:
if (IsContextLost())
return;
if (!ValidateTexImageTarget(2, rawTexImageTarget, WebGLTexImageFunc::TexSubImage))
return ErrorInvalidEnumInfo("texSubImage2D: target", rawTexImageTarget);
const TexImageTarget texImageTarget(rawTexImageTarget);
- if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
- return;
-
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();
+ const TexInternalFormat internalformat = imageInfo.EffectiveInternalFormat();
// Trying to handle the video by GPU directly first
if (TexImageFromVideoElement(texImageTarget, level,
internalformat.get(), format, type, elt))
{
return;
}
@@ -1140,18 +1134,16 @@ protected:
GLsizei width, GLsizei height,
GLsizei levelWidth, GLsizei levelHeight,
WebGLTexImageFunc func);
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,
@@ -1198,17 +1190,17 @@ protected:
}
nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
RefPtr<gfx::DataSourceSurface>& imageOut,
WebGLTexelFormat *format);
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level,
- GLenum internalformat,
+ TexInternalFormat internalformat,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
bool sub);
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -671,17 +671,17 @@ WebGLContext::BindFakeBlackTexturesHelpe
WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
continue;
}
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
- FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().InternalFormat());
+ FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().EffectiveInternalFormat());
UniquePtr<FakeBlackTexture>&
blackTexturePtr = alpha
? transparentTextureScopedPtr
: opaqueTextureScopedPtr;
if (!blackTexturePtr) {
GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
blackTexturePtr = MakeUnique<FakeBlackTexture>(gl, target, format);
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -349,17 +349,17 @@ WebGLContext::CheckFramebufferStatus(GLe
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
return mBoundFramebuffer->CheckFramebufferStatus().get();
}
void
WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level,
- GLenum internalformat,
+ TexInternalFormat internalformat,
GLint xoffset,
GLint yoffset,
GLint x,
GLint y,
GLsizei width,
GLsizei height,
bool sub)
{
@@ -367,27 +367,27 @@ WebGLContext::CopyTexSubImage2D_base(Tex
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;
// TODO: This changes with color_buffer_float. Reassess when the
// patch lands.
- if (!ValidateTexImage(2, texImageTarget, level, internalformat,
+ if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
xoffset, yoffset, 0,
width, height, 0,
0,
LOCAL_GL_NONE, LOCAL_GL_NONE,
func))
{
return;
}
- if (!ValidateCopyTexImage(internalformat, func))
+ if (!ValidateCopyTexImage(internalformat.get(), func))
return;
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
MakeContextCurrent();
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
@@ -396,60 +396,60 @@ WebGLContext::CopyTexSubImage2D_base(Tex
return ErrorInvalidOperation("%s: no texture is bound to this target");
if (tex->IsImmutable()) {
if (!sub) {
return ErrorInvalidOperation("copyTexImage2D: disallowed because the texture bound to this target has already been made immutable by texStorage2D");
}
}
+ TexType framebuffertype = LOCAL_GL_NONE;
+ if (mBoundFramebuffer) {
+ TexInternalFormat framebuffereffectiveformat = mBoundFramebuffer->ColorAttachment(0).EffectiveInternalFormat();
+ framebuffertype = TypeFromInternalFormat(framebuffereffectiveformat);
+ } else {
+ // FIXME - here we're assuming that the default framebuffer is backed by UNSIGNED_BYTE
+ // that might not always be true, say if we had a 16bpp default framebuffer.
+ framebuffertype = LOCAL_GL_UNSIGNED_BYTE;
+ }
+
+ TexInternalFormat effectiveinternalformat =
+ EffectiveInternalFormatFromUnsizedInternalFormatAndType(internalformat, framebuffertype);
+
+ // this should never fail, validation happened earlier.
+ MOZ_ASSERT(effectiveinternalformat != LOCAL_GL_NONE);
+
+ // check if the memory size of this texture may change with this call
+ bool sizeMayChange = !sub;
+ if (!sub && tex->HasImageInfoAt(texImageTarget, level)) {
+ const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
+ sizeMayChange = width != imageInfo.Width() ||
+ height != imageInfo.Height() ||
+ effectiveinternalformat != imageInfo.EffectiveInternalFormat();
+ }
+
+ if (sizeMayChange)
+ GetAndFlushUnderlyingGLErrors();
+
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, framebufferWidth, framebufferHeight)) {
if (sub)
gl->fCopyTexSubImage2D(texImageTarget.get(), level, xoffset, yoffset, x, y, width, height);
else
- gl->fCopyTexImage2D(texImageTarget.get(), level, internalformat, x, y, width, height, 0);
+ gl->fCopyTexImage2D(texImageTarget.get(), level, internalformat.get(), x, y, width, height, 0);
} else {
// the rect doesn't fit in the framebuffer
- /*** first, we initialize the texture as black ***/
-
- // first, compute the size of the buffer we should allocate to initialize the texture as black
-
- if (!ValidateTexInputData(LOCAL_GL_UNSIGNED_BYTE, -1, func))
- return;
-
- uint32_t texelSize = GetBitsPerTexel(internalformat, LOCAL_GL_UNSIGNED_BYTE) / 8;
-
- CheckedUint32 checked_neededByteLength =
- GetImageSize(height, width, texelSize, mPixelStoreUnpackAlignment);
-
- if (!checked_neededByteLength.isValid())
- return ErrorInvalidOperation("%s: integer overflow computing the needed buffer size", info);
-
- uint32_t bytesNeeded = checked_neededByteLength.value();
-
- // now that the size is known, create the buffer
-
- // We need some zero pages, because GL doesn't guarantee the
- // contents of a texture allocated with nullptr data.
- // Hopefully calloc will just mmap zero pages here.
- void* tempZeroData = calloc(1, bytesNeeded);
- if (!tempZeroData)
- return ErrorOutOfMemory("%s: could not allocate %d bytes (for zero fill)", info, bytesNeeded);
-
- // now initialize the texture as black
-
- if (sub)
- gl->fTexSubImage2D(texImageTarget.get(), level, 0, 0, width, height,
- internalformat, LOCAL_GL_UNSIGNED_BYTE, tempZeroData);
- else
- gl->fTexImage2D(texImageTarget.get(), level, internalformat, width, height,
- 0, internalformat, LOCAL_GL_UNSIGNED_BYTE, tempZeroData);
- free(tempZeroData);
+ // first, we initialize the texture as black
+ if (!sub) {
+ tex->SetImageInfo(texImageTarget, level, width, height,
+ effectiveinternalformat,
+ WebGLImageDataStatus::UninitializedImageData);
+ tex->DoDeferredImageInitialization(texImageTarget, level);
+ }
// if we are completely outside of the framebuffer, we can exit now with our black texture
if ( x >= framebufferWidth
|| x+width <= 0
|| y >= framebufferHeight
|| y+height <= 0)
{
// we are completely outside of range, can exit now with buffer filled with zeros
@@ -463,16 +463,30 @@ WebGLContext::CopyTexSubImage2D_base(Tex
GLint actual_y = clamped(y, 0, framebufferHeight);
GLint actual_y_plus_height = clamped(y + height, 0, framebufferHeight);
GLsizei actual_height = actual_y_plus_height - actual_y;
GLint actual_yoffset = yoffset + actual_y - y;
gl->fCopyTexSubImage2D(texImageTarget.get(), level, actual_xoffset, actual_yoffset, actual_x, actual_y, actual_width, actual_height);
}
+
+ if (sizeMayChange) {
+ GLenum error = GetAndFlushUnderlyingGLErrors();
+ if (error) {
+ GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
+ return;
+ }
+ }
+
+ if (!sub) {
+ tex->SetImageInfo(texImageTarget, level, width, height,
+ effectiveinternalformat,
+ WebGLImageDataStatus::InitializedImageData);
+ }
}
void
WebGLContext::CopyTexImage2D(GLenum rawTexImgTarget,
GLint level,
GLenum internalformat,
GLint x,
GLint y,
@@ -499,47 +513,17 @@ WebGLContext::CopyTexImage2D(GLenum rawT
}
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();
- }
-
- if (sizeMayChange)
- GetAndFlushUnderlyingGLErrors();
-
- 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,
- LOCAL_GL_UNSIGNED_BYTE, /* dummy, artifact of us storing
- the wrong data in ImageInfo */
- WebGLImageDataStatus::InitializedImageData);
+ CopyTexSubImage2D_base(rawTexImgTarget, level, internalformat, 0, 0, x, y, width, height, false);
}
void
WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
GLint level,
GLint xoffset,
GLint yoffset,
GLint x,
@@ -597,17 +581,21 @@ WebGLContext::CopyTexSubImage2D(GLenum r
if (!mBoundFramebuffer)
ClearBackbufferIfNeeded();
if (imageInfo.HasUninitializedImageData()) {
tex->DoDeferredImageInitialization(texImageTarget, level);
}
- return CopyTexSubImage2D_base(texImageTarget, level, imageInfo.InternalFormat().get(), xoffset, yoffset, x, y, width, height, true);
+ TexInternalFormat internalformat;
+ TexType type;
+ UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(imageInfo.EffectiveInternalFormat(),
+ &internalformat, &type);
+ return CopyTexSubImage2D_base(texImageTarget, level, internalformat, xoffset, yoffset, x, y, width, height, true);
}
already_AddRefed<WebGLProgram>
WebGLContext::CreateProgram()
{
if (IsContextLost())
return nullptr;
@@ -917,17 +905,17 @@ WebGLContext::GenerateMipmap(GLenum rawT
if (!tex->HasImageInfoAt(imageTarget, 0))
{
return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
}
if (!tex->IsFirstImagePowerOfTwo())
return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
- TexInternalFormat internalformat = tex->ImageInfoAt(imageTarget, 0).InternalFormat();
+ TexInternalFormat internalformat = tex->ImageInfoAt(imageTarget, 0).EffectiveInternalFormat();
if (IsTextureFormatCompressed(internalformat))
return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
(IsGLDepthFormat(internalformat) || IsGLDepthStencilFormat(internalformat)))
{
return ErrorInvalidOperation("generateMipmap: "
"A texture that has a base internal format of "
@@ -1178,22 +1166,27 @@ WebGLContext::GetFramebufferAttachmentPa
}
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
return JS::NullValue();
} else if (fba.Texture()) {
switch (pname) {
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
- const TexInternalFormat internalformat =
- fba.Texture()->ImageInfoBase().InternalFormat();
- return (internalformat == LOCAL_GL_SRGB ||
- internalformat == LOCAL_GL_SRGB_ALPHA) ?
- JS::NumberValue(uint32_t(LOCAL_GL_SRGB)) :
- JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
+ const TexInternalFormat effectiveinternalformat =
+ fba.Texture()->ImageInfoBase().EffectiveInternalFormat();
+ TexInternalFormat unsizedinternalformat = LOCAL_GL_NONE;
+ TexType type = LOCAL_GL_NONE;
+ UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(
+ effectiveinternalformat, &unsizedinternalformat, &type);
+ MOZ_ASSERT(unsizedinternalformat != LOCAL_GL_NONE);
+ const bool srgb = unsizedinternalformat == LOCAL_GL_SRGB ||
+ unsizedinternalformat == LOCAL_GL_SRGB_ALPHA;
+ return srgb ? JS::NumberValue(uint32_t(LOCAL_GL_SRGB))
+ : JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
}
break;
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
return JS::NumberValue(uint32_t(LOCAL_GL_TEXTURE));
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
return WebGLObjectAsJSValue(cx, fba.Texture(), rv);
@@ -1219,28 +1212,29 @@ WebGLContext::GetFramebufferAttachmentPa
ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot component"
" type of depth-stencil attachments.");
return JS::NullValue();
}
if (!fba.IsComplete())
return JS::NumberValue(uint32_t(LOCAL_GL_NONE));
- uint32_t ret = LOCAL_GL_NONE;
- TexType type = fba.Texture()->ImageInfoAt(fba.ImageTarget(),
- fba.MipLevel()).Type();
+ TexInternalFormat effectiveinternalformat =
+ fba.Texture()->ImageInfoAt(fba.ImageTarget(), fba.MipLevel()).EffectiveInternalFormat();
+ TexType type = TypeFromInternalFormat(effectiveinternalformat);
+ GLenum ret = LOCAL_GL_NONE;
switch (type.get()) {
case LOCAL_GL_UNSIGNED_BYTE:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
ret = LOCAL_GL_UNSIGNED_NORMALIZED;
break;
case LOCAL_GL_FLOAT:
- case LOCAL_GL_HALF_FLOAT_OES:
+ case LOCAL_GL_HALF_FLOAT:
ret = LOCAL_GL_FLOAT;
break;
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_UNSIGNED_INT:
ret = LOCAL_GL_UNSIGNED_INT;
break;
default:
MOZ_ASSERT(false, "Unhandled RB component type.");
@@ -3348,17 +3342,17 @@ WebGLContext::CompressedTexImage2D(GLenu
return ErrorInvalidOperation(
"compressedTexImage2D: disallowed because the texture bound to "
"this target has already been made immutable by texStorage2D");
}
MakeContextCurrent();
gl->fCompressedTexImage2D(texImageTarget.get(), level, internalformat, width, height, border, byteLength, view.Data());
- tex->SetImageInfo(texImageTarget, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
+ tex->SetImageInfo(texImageTarget, level, width, height, internalformat,
WebGLImageDataStatus::InitializedImageData);
}
void
WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint xoffset,
GLint yoffset, GLsizei width, GLsizei height,
GLenum internalformat,
const ArrayBufferView& view)
@@ -3382,17 +3376,17 @@ WebGLContext::CompressedTexSubImage2D(GL
}
const TexImageTarget texImageTarget(rawTexImgTarget);
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex);
WebGLTexture::ImageInfo& levelInfo = tex->ImageInfoAt(texImageTarget, level);
- if (internalformat != levelInfo.InternalFormat()) {
+ 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))
return;
@@ -3594,41 +3588,47 @@ WebGLContext::GetShaderTranslatedSource(
if (!ValidateObject("getShaderTranslatedSource: shader", shader))
return;
retval.Assign(shader->TranslatedSource());
}
GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget,
GLint level,
- TexInternalFormat internalFormat,
+ TexInternalFormat internalformat,
GLsizei width,
GLsizei height,
GLint border,
TexFormat format,
TexType type,
const GLvoid *data)
{
WebGLTexture *tex = activeBoundTextureForTexImageTarget(texImageTarget);
MOZ_ASSERT(tex != nullptr, "no texture bound");
+ TexInternalFormat effectiveInternalFormat =
+ EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
bool sizeMayChange = true;
if (tex->HasImageInfoAt(texImageTarget, level)) {
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
sizeMayChange = width != imageInfo.Width() ||
height != imageInfo.Height() ||
- internalFormat != imageInfo.InternalFormat();
+ effectiveInternalFormat != imageInfo.EffectiveInternalFormat();
}
// Convert to format and type required by OpenGL 'driver'.
- GLenum driverType = DriverTypeFromType(gl, type);
+ GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
- DriverFormatsFromFormatAndType(gl, internalFormat, type, &driverInternalFormat, &driverFormat);
+ DriverFormatsFromEffectiveInternalFormat(gl,
+ effectiveInternalFormat,
+ &driverInternalFormat,
+ &driverFormat,
+ &driverType);
if (sizeMayChange) {
GetAndFlushUnderlyingGLErrors();
}
gl->fTexImage2D(texImageTarget.get(), level, driverInternalFormat, width, height, border, driverFormat, driverType, data);
GLenum error = LOCAL_GL_NO_ERROR;
@@ -3647,16 +3647,20 @@ WebGLContext::TexImage2D_base(TexImageTa
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 (type == LOCAL_GL_HALF_FLOAT_OES) {
+ type = LOCAL_GL_HALF_FLOAT;
+ }
+
if (!ValidateTexImage(2, texImageTarget, level, internalformat,
0, 0, 0,
width, height, 0,
border, format, type, func))
{
return;
}
@@ -3669,17 +3673,24 @@ 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(internalformat, type);
+ TexInternalFormat effectiveinternalformat =
+ EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
+
+ if (effectiveinternalformat == LOCAL_GL_NONE) {
+ return ErrorInvalidOperation("texImage2D: bad combination of internalformat and type");
+ }
+
+ WebGLTexelFormat dstFormat = GetWebGLTexelFormat(effectiveinternalformat);
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;
@@ -3707,18 +3718,20 @@ WebGLContext::TexImage2D_base(TexImageTa
}
MakeContextCurrent();
nsAutoArrayPtr<uint8_t> convertedData;
void* pixels = nullptr;
WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
if (byteLength) {
+ size_t bitspertexel = GetBitsPerTexel(effectiveinternalformat);
+ MOZ_ASSERT((bitspertexel % 8) == 0); // should not have compressed formats here.
+ size_t dstTexelSize = bitspertexel / 8;
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
- 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)
@@ -3747,17 +3760,18 @@ WebGLContext::TexImage2D_base(TexImageTa
return;
}
// in all of the code paths above, we should have either initialized data,
// or allocated data and left it uninitialized, but in any case we shouldn't
// have NoImageData at this point.
MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
- tex->SetImageInfo(texImageTarget, level, width, height, internalformat, type, imageInfoStatusIfSuccess);
+ tex->SetImageInfo(texImageTarget, level, width, height,
+ effectiveinternalformat, imageInfoStatusIfSuccess);
}
void
WebGLContext::TexImage2D(GLenum rawTarget, GLint level,
GLenum internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format,
GLenum type, const Nullable<ArrayBufferView> &pixels, ErrorResult& rv)
{
@@ -3825,39 +3839,53 @@ 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 (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");
}
+
+ if (!tex->HasImageInfoAt(texImageTarget, level)) {
+ return ErrorInvalidOperation("texSubImage2D: no previously defined texture image");
+ }
+
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
- const TexInternalFormat internalformat = imageInfo.InternalFormat();
-
- if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
+ const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
+ TexInternalFormat existingUnsizedInternalFormat = LOCAL_GL_NONE;
+ TexType existingType = LOCAL_GL_NONE;
+ UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(existingEffectiveInternalFormat,
+ &existingUnsizedInternalFormat,
+ &existingType);
+
+ if (!ValidateTexImage(2, texImageTarget, level, existingUnsizedInternalFormat.get(),
xoffset, yoffset, 0,
width, height, 0,
0, format, type, func))
{
return;
}
if (!ValidateTexInputData(type, jsArrayType, func))
return;
- if (imageInfo.Type() != type) {
- return ErrorInvalidOperation("texSubImage2D: type parameter does not match the existing image");
+ if (type != existingType) {
+ return ErrorInvalidOperation("texSubImage2D: type differs from that of the existing image");
}
- WebGLTexelFormat dstFormat = GetWebGLTexelFormat(internalformat, type);
+ WebGLTexelFormat dstFormat = GetWebGLTexelFormat(existingEffectiveInternalFormat);
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 =
@@ -3877,17 +3905,17 @@ WebGLContext::TexSubImage2D_base(TexImag
return ErrorInvalidOperation("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
if (imageInfo.HasUninitializedImageData())
tex->DoDeferredImageInitialization(texImageTarget, level);
MakeContextCurrent();
size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
- uint32_t dstTexelSize = GetBitsPerTexel(internalformat, type) / 8;
+ uint32_t dstTexelSize = GetBitsPerTexel(existingEffectiveInternalFormat) / 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
@@ -3901,20 +3929,24 @@ WebGLContext::TexSubImage2D_base(TexImag
convertedData = new uint8_t[convertedDataSize];
ConvertImage(width, height, srcStride, dstStride,
static_cast<const uint8_t*>(data), convertedData,
actualSrcFormat, srcPremultiplied,
dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
pixels = reinterpret_cast<void*>(convertedData.get());
}
- GLenum driverType = DriverTypeFromType(gl, type);
+ GLenum driverType = LOCAL_GL_NONE;
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
- DriverFormatsFromFormatAndType(gl, internalformat, type, &driverInternalFormat, &driverFormat);
+ DriverFormatsFromEffectiveInternalFormat(gl,
+ existingEffectiveInternalFormat,
+ &driverInternalFormat,
+ &driverFormat,
+ &driverType);
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,
@@ -4061,129 +4093,47 @@ BaseTypeAndSizeFromUniformType(GLenum uT
default:
return false;
}
return true;
}
-WebGLTexelFormat mozilla::GetWebGLTexelFormat(TexInternalFormat internalformat, TexType type)
+WebGLTexelFormat
+mozilla::GetWebGLTexelFormat(TexInternalFormat effectiveinternalformat)
{
- //
- // WEBGL_depth_texture
- if (internalformat == LOCAL_GL_DEPTH_COMPONENT) {
- switch (type.get()) {
- case LOCAL_GL_UNSIGNED_SHORT:
- return WebGLTexelFormat::D16;
- case LOCAL_GL_UNSIGNED_INT:
- return WebGLTexelFormat::D32;
- }
-
- MOZ_CRASH("Invalid WebGL texture format/type?");
- }
-
- if (internalformat == LOCAL_GL_DEPTH_STENCIL) {
- switch (type.get()) {
- case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
- return WebGLTexelFormat::D24S8;
- }
-
- MOZ_CRASH("Invalid WebGL texture format/type?");
- }
-
- if (internalformat == LOCAL_GL_DEPTH_COMPONENT16) {
- return WebGLTexelFormat::D16;
- }
-
- if (internalformat == LOCAL_GL_DEPTH_COMPONENT32) {
- return WebGLTexelFormat::D32;
- }
-
- if (internalformat == LOCAL_GL_DEPTH24_STENCIL8) {
- return WebGLTexelFormat::D24S8;
- }
-
- if (type == LOCAL_GL_UNSIGNED_BYTE) {
- switch (internalformat.get()) {
- case LOCAL_GL_RGBA:
- case LOCAL_GL_SRGB_ALPHA_EXT:
- return WebGLTexelFormat::RGBA8;
- case LOCAL_GL_RGB:
- case LOCAL_GL_SRGB_EXT:
- return WebGLTexelFormat::RGB8;
- case LOCAL_GL_ALPHA:
- return WebGLTexelFormat::A8;
- case LOCAL_GL_LUMINANCE:
- return WebGLTexelFormat::R8;
- case LOCAL_GL_LUMINANCE_ALPHA:
- return WebGLTexelFormat::RA8;
- }
-
- MOZ_CRASH("Invalid WebGL texture format/type?");
- }
-
- if (type == LOCAL_GL_FLOAT) {
- // OES_texture_float
- switch (internalformat.get()) {
- case LOCAL_GL_RGBA:
- case LOCAL_GL_RGBA32F:
- return WebGLTexelFormat::RGBA32F;
- case LOCAL_GL_RGB:
- case LOCAL_GL_RGB32F:
- return WebGLTexelFormat::RGB32F;
- case LOCAL_GL_ALPHA:
- case LOCAL_GL_ALPHA32F_ARB:
- return WebGLTexelFormat::A32F;
- case LOCAL_GL_LUMINANCE:
- case LOCAL_GL_LUMINANCE32F_ARB:
- return WebGLTexelFormat::R32F;
- case LOCAL_GL_LUMINANCE_ALPHA:
- case LOCAL_GL_LUMINANCE_ALPHA32F_ARB:
- return WebGLTexelFormat::RA32F;
- }
-
- MOZ_CRASH("Invalid WebGL texture format/type?");
- } else if (type == LOCAL_GL_HALF_FLOAT_OES) {
- // OES_texture_half_float
- switch (internalformat.get()) {
- case LOCAL_GL_RGBA:
- case LOCAL_GL_RGBA16F:
- return WebGLTexelFormat::RGBA16F;
- case LOCAL_GL_RGB:
- case LOCAL_GL_RGB16F:
- return WebGLTexelFormat::RGB16F;
- case LOCAL_GL_ALPHA:
- case LOCAL_GL_ALPHA16F_ARB:
- return WebGLTexelFormat::A16F;
- case LOCAL_GL_LUMINANCE:
- case LOCAL_GL_LUMINANCE16F_ARB:
- return WebGLTexelFormat::R16F;
- case LOCAL_GL_LUMINANCE_ALPHA:
- case LOCAL_GL_LUMINANCE_ALPHA16F_ARB:
- return WebGLTexelFormat::RA16F;
- default:
- MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
- return WebGLTexelFormat::BadFormat;
- }
- }
-
- switch (type.get()) {
- case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
- return WebGLTexelFormat::RGBA4444;
- case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
- return WebGLTexelFormat::RGBA5551;
- case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
- return WebGLTexelFormat::RGB565;
+ switch (effectiveinternalformat.get()) {
+ case LOCAL_GL_DEPTH_COMPONENT16: return WebGLTexelFormat::D16;
+ case LOCAL_GL_DEPTH_COMPONENT24: return WebGLTexelFormat::D32;
+ case LOCAL_GL_DEPTH24_STENCIL8: return WebGLTexelFormat::D24S8;
+ case LOCAL_GL_RGBA8: return WebGLTexelFormat::RGBA8;
+ case LOCAL_GL_SRGB8_ALPHA8: return WebGLTexelFormat::RGBA8;
+ case LOCAL_GL_RGB8: return WebGLTexelFormat::RGB8;
+ case LOCAL_GL_SRGB8: return WebGLTexelFormat::RGB8;
+ case LOCAL_GL_ALPHA8: return WebGLTexelFormat::A8;
+ case LOCAL_GL_LUMINANCE8: return WebGLTexelFormat::R8;
+ case LOCAL_GL_LUMINANCE8_ALPHA8: return WebGLTexelFormat::RA8;
+ case LOCAL_GL_RGBA32F: return WebGLTexelFormat::RGBA32F;
+ case LOCAL_GL_RGB32F: return WebGLTexelFormat::RGB32F;
+ case LOCAL_GL_ALPHA32F_EXT: return WebGLTexelFormat::A32F;
+ case LOCAL_GL_LUMINANCE32F_EXT: return WebGLTexelFormat::R32F;
+ case LOCAL_GL_LUMINANCE_ALPHA32F_EXT: return WebGLTexelFormat::RA32F;
+ case LOCAL_GL_RGBA16F: return WebGLTexelFormat::RGBA16F;
+ case LOCAL_GL_RGB16F: return WebGLTexelFormat::RGB16F;
+ case LOCAL_GL_ALPHA16F_EXT: return WebGLTexelFormat::A16F;
+ case LOCAL_GL_LUMINANCE16F_EXT: return WebGLTexelFormat::R16F;
+ case LOCAL_GL_LUMINANCE_ALPHA16F_EXT: return WebGLTexelFormat::RA16F;
+ case LOCAL_GL_RGBA4: return WebGLTexelFormat::RGBA4444;
+ case LOCAL_GL_RGB5_A1: return WebGLTexelFormat::RGBA5551;
+ case LOCAL_GL_RGB565: return WebGLTexelFormat::RGB565;
default:
- MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
+ MOZ_CRASH("Unhandled format");
return WebGLTexelFormat::BadFormat;
}
-
- MOZ_CRASH("Invalid WebGL texture format/type?");
}
void
WebGLContext::BlendColor(GLclampf r, GLclampf g, GLclampf b, GLclampf a) {
if (IsContextLost())
return;
MakeContextCurrent();
gl->fBlendColor(r, g, b, a);
--- a/dom/canvas/WebGLContextUtils.cpp
+++ b/dom/canvas/WebGLContextUtils.cpp
@@ -26,39 +26,38 @@
#include "mozilla/dom/ScriptSettings.h"
namespace mozilla {
using namespace gl;
bool
-IsGLDepthFormat(TexInternalFormat webGLFormat)
+IsGLDepthFormat(TexInternalFormat internalformat)
{
- return (webGLFormat == LOCAL_GL_DEPTH_COMPONENT ||
- webGLFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
- webGLFormat == LOCAL_GL_DEPTH_COMPONENT32);
+ TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
+ return unsizedformat == LOCAL_GL_DEPTH_COMPONENT;
}
bool
-IsGLDepthStencilFormat(TexInternalFormat webGLFormat)
+IsGLDepthStencilFormat(TexInternalFormat internalformat)
{
- return (webGLFormat == LOCAL_GL_DEPTH_STENCIL ||
- webGLFormat == LOCAL_GL_DEPTH24_STENCIL8);
+ TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
+ return unsizedformat == LOCAL_GL_DEPTH_STENCIL;
}
bool
-FormatHasAlpha(TexInternalFormat webGLFormat)
+FormatHasAlpha(TexInternalFormat internalformat)
{
- return webGLFormat == LOCAL_GL_RGBA ||
- webGLFormat == LOCAL_GL_LUMINANCE_ALPHA ||
- webGLFormat == LOCAL_GL_ALPHA ||
- webGLFormat == LOCAL_GL_RGBA4 ||
- webGLFormat == LOCAL_GL_RGB5_A1 ||
- webGLFormat == LOCAL_GL_SRGB_ALPHA;
+ 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;
}
TexTarget
TexImageTargetToTexTarget(TexImageTarget texImageTarget)
{
switch (texImageTarget.get()) {
case LOCAL_GL_TEXTURE_2D:
return LOCAL_GL_TEXTURE_2D;
@@ -71,21 +70,22 @@ TexImageTargetToTexTarget(TexImageTarget
return LOCAL_GL_TEXTURE_CUBE_MAP;
default:
MOZ_ASSERT(false, "Bad texture conversion");
// Should be caught by the constructor for TexTarget
return LOCAL_GL_NONE;
}
}
-GLComponents::GLComponents(TexInternalFormat format)
+GLComponents::GLComponents(TexInternalFormat internalformat)
{
+ TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
mComponents = 0;
- switch (format.get()) {
+ switch (unsizedformat.get()) {
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;
@@ -112,162 +112,287 @@ GLComponents::GLComponents(TexInternalFo
}
bool
GLComponents::IsSubsetOf(const GLComponents& other) const
{
return (mComponents | other.mComponents) == other.mComponents;
}
+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.
+ */
+TexInternalFormat
+EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
+ TexType type)
+{
+ MOZ_ASSERT(TypeFromInternalFormat(internalformat) == LOCAL_GL_NONE);
+
+#define HANDLE_WEBGL_INTERNAL_FORMAT(table_effectiveinternalformat, table_internalformat, table_type) \
+ if (internalformat == table_internalformat && type == table_type) { \
+ return table_effectiveinternalformat; \
+ }
+
+#include "WebGLInternalFormatsTable.h"
+
+ // If we're here, that means that type was incompatible with the given internalformat.
+ return LOCAL_GL_NONE;
+}
+
+void
+UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
+ TexInternalFormat* out_internalformat,
+ TexType* out_type)
+{
+ MOZ_ASSERT(TypeFromInternalFormat(effectiveinternalformat) != LOCAL_GL_NONE);
+
+ MOZ_ASSERT(out_internalformat);
+ MOZ_ASSERT(out_type);
+
+ 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
+ }
+
+ *out_internalformat = internalformat;
+ *out_type = type;
+}
+
+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;
+ }
+}
+
/**
- * Convert WebGL/ES format and type into GL internal
- * format valid for underlying driver.
+ * Convert effective internalformat into GL function parameters
+ * valid for underlying driver.
*/
void
-DriverFormatsFromFormatAndType(GLContext* gl, TexInternalFormat webGLInternalFormat, TexType webGLType,
- GLenum* out_driverInternalFormat, GLenum* out_driverFormat)
+DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
+ TexInternalFormat effectiveinternalformat,
+ GLenum* out_driverInternalFormat,
+ GLenum* out_driverFormat,
+ GLenum* out_driverType)
{
MOZ_ASSERT(out_driverInternalFormat);
MOZ_ASSERT(out_driverFormat);
+ MOZ_ASSERT(out_driverType);
- // ES2 requires that format == internalformat; floating-point is
- // indicated purely by the type that's loaded. For desktop GL, we
- // have to specify a floating point internal format.
- if (gl->IsGLES()) {
- *out_driverFormat = *out_driverInternalFormat = webGLInternalFormat.get();
- return;
+ TexInternalFormat unsizedinternalformat = LOCAL_GL_NONE;
+ TexType type = LOCAL_GL_NONE;
+
+ 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;
}
- GLenum internalFormat = LOCAL_GL_NONE;
- GLenum format = LOCAL_GL_NONE;
-
- if (webGLInternalFormat == LOCAL_GL_DEPTH_COMPONENT) {
- format = LOCAL_GL_DEPTH_COMPONENT;
- if (webGLType == LOCAL_GL_UNSIGNED_SHORT)
- internalFormat = LOCAL_GL_DEPTH_COMPONENT16;
- else if (webGLType == LOCAL_GL_UNSIGNED_INT)
- internalFormat = LOCAL_GL_DEPTH_COMPONENT32;
- } else if (webGLInternalFormat == LOCAL_GL_DEPTH_STENCIL) {
- format = LOCAL_GL_DEPTH_STENCIL;
- if (webGLType == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
- internalFormat = LOCAL_GL_DEPTH24_STENCIL8;
- } else {
- switch (webGLType.get()) {
- case LOCAL_GL_UNSIGNED_BYTE:
- case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
- case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
- case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
- format = internalFormat = webGLInternalFormat.get();
- break;
-
- case LOCAL_GL_FLOAT:
- switch (webGLInternalFormat.get()) {
- case LOCAL_GL_RGBA:
- format = LOCAL_GL_RGBA;
- internalFormat = LOCAL_GL_RGBA32F;
- break;
-
- case LOCAL_GL_RGB:
- format = LOCAL_GL_RGB;
- internalFormat = LOCAL_GL_RGB32F;
- break;
-
- case LOCAL_GL_ALPHA:
- format = LOCAL_GL_ALPHA;
- internalFormat = LOCAL_GL_ALPHA32F_ARB;
- break;
+ // driverFormat: always just the unsized internalformat that we just got
+ GLenum driverFormat = unsizedinternalformat.get();
- case LOCAL_GL_LUMINANCE:
- format = LOCAL_GL_LUMINANCE;
- internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
- break;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- format = LOCAL_GL_LUMINANCE_ALPHA;
- internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
- break;
- }
- break;
-
- case LOCAL_GL_HALF_FLOAT_OES:
- switch (webGLInternalFormat.get()) {
- case LOCAL_GL_RGBA:
- format = LOCAL_GL_RGBA;
- internalFormat = LOCAL_GL_RGBA16F;
- break;
-
- case LOCAL_GL_RGB:
- format = LOCAL_GL_RGB;
- internalFormat = LOCAL_GL_RGB16F;
- break;
-
- case LOCAL_GL_ALPHA:
- format = LOCAL_GL_ALPHA;
- internalFormat = LOCAL_GL_ALPHA16F_ARB;
- break;
-
- case LOCAL_GL_LUMINANCE:
- format = LOCAL_GL_LUMINANCE;
- internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
- break;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- format = LOCAL_GL_LUMINANCE_ALPHA;
- internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
- break;
- }
- break;
-
- default:
- break;
+ // 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;
}
- // Handle ES2 and GL differences when supporting sRGB internal formats. GL ES
- // requires that format == internalformat, but GL will fail in this case.
- // GL requires:
- // format -> internalformat
- // GL_RGB GL_SRGB_EXT
- // GL_RGBA GL_SRGB_ALPHA_EXT
- switch (webGLInternalFormat.get()) {
- case LOCAL_GL_SRGB:
- format = LOCAL_GL_RGB;
- internalFormat = LOCAL_GL_SRGB;
- break;
- case LOCAL_GL_SRGB_ALPHA:
- format = LOCAL_GL_RGBA;
- internalFormat = LOCAL_GL_SRGB_ALPHA;
- break;
+ // 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();
}
}
- MOZ_ASSERT(webGLInternalFormat != LOCAL_GL_NONE && internalFormat != LOCAL_GL_NONE,
- "Coding mistake -- bad format/type passed?");
-
- *out_driverInternalFormat = internalFormat;
- *out_driverFormat = format;
+ *out_driverInternalFormat = driverInternalFormat;
+ *out_driverFormat = driverFormat;
+ *out_driverType = driverType;
}
-GLenum
-DriverTypeFromType(GLContext* gl, TexType webGLType)
+/**
+ * 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)
{
- GLenum type = webGLType.get();
+ 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;
- if (gl->IsGLES())
- return type;
+ 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;
- // convert type for half float if not on GLES2
- if (type == LOCAL_GL_HALF_FLOAT_OES) {
- if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
- return LOCAL_GL_HALF_FLOAT;
- } else {
- MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
- }
+ 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;
}
-
- return type;
}
void
WebGLContext::GenerateWarning(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
--- a/dom/canvas/WebGLContextUtils.h
+++ b/dom/canvas/WebGLContextUtils.h
@@ -11,19 +11,38 @@
#include "mozilla/Assertions.h"
#include "mozilla/dom/BindingUtils.h"
namespace mozilla {
bool IsGLDepthFormat(TexInternalFormat webGLFormat);
bool IsGLDepthStencilFormat(TexInternalFormat webGLFormat);
bool FormatHasAlpha(TexInternalFormat webGLFormat);
-void DriverFormatsFromFormatAndType(gl::GLContext* gl, TexInternalFormat webGLFormat, TexType webGLType,
- GLenum* out_driverInternalFormat, GLenum* out_driverFormat);
-GLenum DriverTypeFromType(gl::GLContext* gl, TexType webGLType);
+void
+DriverFormatsFromEffectiveInternalFormat(gl::GLContext* gl,
+ TexInternalFormat internalformat,
+ GLenum* out_driverInternalFormat,
+ GLenum* out_driverFormat,
+ GLenum* out_driverType);
+TexInternalFormat
+EffectiveInternalFormatFromInternalFormatAndType(TexInternalFormat internalformat,
+ TexType type);
+TexInternalFormat
+EffectiveInternalFormatFromUnsizedInternalFormatAndType(TexInternalFormat internalformat,
+ TexType type);
+void
+UnsizedInternalFormatAndTypeFromEffectiveInternalFormat(TexInternalFormat effectiveinternalformat,
+ TexInternalFormat* out_internalformat,
+ TexType* out_type);
+TexType
+TypeFromInternalFormat(TexInternalFormat internalformat);
+TexInternalFormat
+UnsizedInternalFormatFromInternalFormat(TexInternalFormat internalformat);
+size_t
+GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
// For use with the different texture calls, i.e.
// TexImage2D, CopyTex[Sub]Image2D, ...
// that take a "target" parameter. This parameter is not always the same as
// the texture binding location, like GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP.
// For example, cube maps would pass GL_TEXTURE_CUBE_MAP_[POS|NEG]_[X|Y|Z]
// instead of just GL_TEXTURE_CUBE_MAP.
//
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -668,17 +668,17 @@ WebGLContext::ValidateTexImageType(GLenu
bool validType = IsExtensionEnabled(WebGLExtensionID::OES_texture_float);
if (!validType)
ErrorInvalidEnum("%s: invalid type %s: need OES_texture_float enabled",
InfoFrom(func), WebGLContext::EnumName(type));
return validType;
}
/* OES_texture_half_float add types */
- if (type == LOCAL_GL_HALF_FLOAT_OES) {
+ 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));
return validType;
}
/* WEBGL_depth_texture added types */
@@ -1021,105 +1021,16 @@ WebGLContext::ValidateTexSubImageSize(GL
ErrorInvalidValue("%s: subtexture rectangle out-of-bounds", InfoFrom(func));
return false;
}
return true;
}
/**
- * Return the bits per texel for format & type combination.
- * Assumes that format & type are a valid combination as checked with
- * ValidateTexImageFormatAndType().
- */
-uint32_t
-WebGLContext::GetBitsPerTexel(TexInternalFormat format, TexType type)
-{
- /* Known fixed-sized types */
- if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
- type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
- type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
- {
- return 16;
- }
-
- if (type == LOCAL_GL_UNSIGNED_INT_24_8)
- return 32;
-
- int bitsPerComponent = 0;
- switch (type.get()) {
- case LOCAL_GL_UNSIGNED_BYTE:
- bitsPerComponent = 8;
- break;
-
- case LOCAL_GL_HALF_FLOAT:
- case LOCAL_GL_HALF_FLOAT_OES:
- case LOCAL_GL_UNSIGNED_SHORT:
- bitsPerComponent = 16;
- break;
-
- case LOCAL_GL_FLOAT:
- case LOCAL_GL_UNSIGNED_INT:
- bitsPerComponent = 32;
- break;
-
- default:
- MOZ_ASSERT(false, "Unhandled type.");
- break;
- }
-
- switch (format.get()) {
- // Uncompressed formats
- case LOCAL_GL_ALPHA:
- case LOCAL_GL_LUMINANCE:
- case LOCAL_GL_DEPTH_COMPONENT:
- case LOCAL_GL_DEPTH_STENCIL:
- return 1 * bitsPerComponent;
-
- case LOCAL_GL_LUMINANCE_ALPHA:
- return 2 * bitsPerComponent;
-
- case LOCAL_GL_RGB:
- case LOCAL_GL_RGB32F:
- case LOCAL_GL_SRGB_EXT:
- return 3 * bitsPerComponent;
-
- case LOCAL_GL_RGBA:
- case LOCAL_GL_RGBA32F:
- case LOCAL_GL_SRGB_ALPHA_EXT:
- return 4 * bitsPerComponent;
-
- // Compressed formats
- 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_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;
-
- default:
- break;
- }
-
- MOZ_ASSERT(false, "Unhandled format+type combo.");
- 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)
{
if (IsCompressedFunc(func) || IsCopyFunc(func))
@@ -1136,36 +1047,33 @@ WebGLContext::ValidateTexImageFormatAndT
bool validCombo = false;
switch (format) {
case LOCAL_GL_ALPHA:
case LOCAL_GL_LUMINANCE:
case LOCAL_GL_LUMINANCE_ALPHA:
validCombo = (type == LOCAL_GL_UNSIGNED_BYTE ||
type == LOCAL_GL_HALF_FLOAT ||
- type == LOCAL_GL_HALF_FLOAT_OES ||
type == LOCAL_GL_FLOAT);
break;
case LOCAL_GL_RGB:
case LOCAL_GL_SRGB:
validCombo = (type == LOCAL_GL_UNSIGNED_BYTE ||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5 ||
type == LOCAL_GL_HALF_FLOAT ||
- type == LOCAL_GL_HALF_FLOAT_OES ||
type == LOCAL_GL_FLOAT);
break;
case LOCAL_GL_RGBA:
case LOCAL_GL_SRGB_ALPHA:
validCombo = (type == LOCAL_GL_UNSIGNED_BYTE ||
type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
type == LOCAL_GL_HALF_FLOAT ||
- type == LOCAL_GL_HALF_FLOAT_OES ||
type == LOCAL_GL_FLOAT);
break;
case LOCAL_GL_DEPTH_COMPONENT:
validCombo = (type == LOCAL_GL_UNSIGNED_SHORT ||
type == LOCAL_GL_UNSIGNED_INT);
break;
@@ -1286,17 +1194,16 @@ WebGLContext::ValidateTexInputData(GLenu
// First, we check for packed types
switch (type) {
case LOCAL_GL_UNSIGNED_BYTE:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Uint8);
break;
case LOCAL_GL_HALF_FLOAT:
- case LOCAL_GL_HALF_FLOAT_OES:
case LOCAL_GL_UNSIGNED_SHORT:
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
validInput = (jsArrayType == -1 || jsArrayType == js::Scalar::Uint16);
break;
case LOCAL_GL_UNSIGNED_INT:
@@ -1444,16 +1351,17 @@ WebGLContext::ValidateTexImage(GLuint di
if (IsSubFunc(func)) {
if (!tex->HasImageInfoAt(texImageTarget, level)) {
ErrorInvalidOperation("%s: no texture image previously defined for target %s at level %d",
info, WebGLContext::EnumName(texImageTarget.get()), level);
return false;
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
+
if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
width, height, depth,
imageInfo.Width(), imageInfo.Height(), 0,
func))
{
return false;
}
}
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -74,73 +74,66 @@ WebGLFramebuffer::Attachment::IsDefined(
}
bool
WebGLFramebuffer::Attachment::HasAlpha() const
{
MOZ_ASSERT(HasImage());
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
- return FormatHasAlpha(Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).InternalFormat());
+ return FormatHasAlpha(Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).EffectiveInternalFormat());
else if (Renderbuffer())
return FormatHasAlpha(Renderbuffer()->InternalFormat());
else return false;
}
GLenum
WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const
{
MOZ_ASSERT(attachment.IsDefined());
MOZ_ASSERT(attachment.Texture() || attachment.Renderbuffer());
if (attachment.Texture()) {
const WebGLTexture& tex = *attachment.Texture();
MOZ_ASSERT(tex.HasImageInfoAt(attachment.ImageTarget(), 0));
const WebGLTexture::ImageInfo& imgInfo = tex.ImageInfoAt(attachment.ImageTarget(), 0);
- return imgInfo.InternalFormat().get();
+ return imgInfo.EffectiveInternalFormat().get();
}
if (attachment.Renderbuffer())
return attachment.Renderbuffer()->InternalFormat();
return LOCAL_GL_NONE;
}
-bool
-WebGLFramebuffer::Attachment::IsReadableFloat() const
+TexInternalFormat
+WebGLFramebuffer::Attachment::EffectiveInternalFormat() const
{
const WebGLTexture* tex = Texture();
if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
- GLenum type = tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).Type().get();
- switch (type) {
- case LOCAL_GL_FLOAT:
- case LOCAL_GL_HALF_FLOAT_OES:
- return true;
- }
- return false;
+ return tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).EffectiveInternalFormat();
}
const WebGLRenderbuffer* rb = Renderbuffer();
if (rb) {
- GLenum format = rb->InternalFormat();
- switch (format) {
- case LOCAL_GL_RGB16F:
- case LOCAL_GL_RGBA16F:
- case LOCAL_GL_RGB32F:
- case LOCAL_GL_RGBA32F:
- return true;
- }
- return false;
+ return rb->InternalFormat();
}
- // If we arrive here Attachment isn't correct setup because it has
- // no texture nor render buffer pointer.
- MOZ_ASSERT(false, "Should not get here.");
- return false;
+ return LOCAL_GL_NONE;
+}
+
+bool
+WebGLFramebuffer::Attachment::IsReadableFloat() const
+{
+ TexInternalFormat internalformat = EffectiveInternalFormat();
+ MOZ_ASSERT(internalformat != LOCAL_GL_NONE);
+ TexType type = TypeFromInternalFormat(internalformat);
+ return type == LOCAL_GL_FLOAT ||
+ type == LOCAL_GL_HALF_FLOAT;
}
void
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level)
{
mTexturePtr = tex;
mRenderbufferPtr = nullptr;
mTexImageTarget = target;
@@ -225,65 +218,45 @@ WebGLFramebuffer::Attachment::RectangleO
MOZ_CRASH("Should not get here.");
}
/* The following IsValidFBOTextureXXX functions check the internal
format that is used by GL or GL ES texture formats. This
corresponds to the state that is stored in
WebGLTexture::ImageInfo::InternalFormat()*/
static inline bool
-IsValidFBOTextureColorFormat(GLenum internalFormat)
+IsValidFBOTextureColorFormat(TexInternalFormat internalformat)
{
/* These formats are internal formats for each texture -- the actual
* low level format, which we might have to do conversions for when
* running against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
*
* This function just handles all of them whether desktop GL or ES.
*/
- return (
- /* linear 8-bit formats */
- internalFormat == LOCAL_GL_ALPHA ||
- internalFormat == LOCAL_GL_LUMINANCE ||
- internalFormat == LOCAL_GL_LUMINANCE_ALPHA ||
- internalFormat == LOCAL_GL_RGB ||
- internalFormat == LOCAL_GL_RGBA ||
- /* sRGB 8-bit formats */
- internalFormat == LOCAL_GL_SRGB_EXT ||
- internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
- /* linear float32 formats */
- internalFormat == LOCAL_GL_ALPHA32F_ARB ||
- internalFormat == LOCAL_GL_LUMINANCE32F_ARB ||
- internalFormat == LOCAL_GL_LUMINANCE_ALPHA32F_ARB ||
- internalFormat == LOCAL_GL_RGB32F_ARB ||
- internalFormat == LOCAL_GL_RGBA32F_ARB ||
- /* texture_half_float formats */
- internalFormat == LOCAL_GL_ALPHA16F_ARB ||
- internalFormat == LOCAL_GL_LUMINANCE16F_ARB ||
- internalFormat == LOCAL_GL_LUMINANCE_ALPHA16F_ARB ||
- internalFormat == LOCAL_GL_RGB16F_ARB ||
- internalFormat == LOCAL_GL_RGBA16F_ARB
- );
+ TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
+ return unsizedformat == LOCAL_GL_ALPHA ||
+ unsizedformat == LOCAL_GL_LUMINANCE ||
+ unsizedformat == LOCAL_GL_LUMINANCE_ALPHA ||
+ unsizedformat == LOCAL_GL_RGB ||
+ unsizedformat == LOCAL_GL_RGBA ||
+ unsizedformat == LOCAL_GL_SRGB ||
+ unsizedformat == LOCAL_GL_SRGB_ALPHA;
}
static inline bool
-IsValidFBOTextureDepthFormat(GLenum internalFormat)
+IsValidFBOTextureDepthFormat(GLenum internalformat)
{
- return (
- internalFormat == LOCAL_GL_DEPTH_COMPONENT ||
- internalFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
- internalFormat == LOCAL_GL_DEPTH_COMPONENT32);
+ return IsGLDepthFormat(internalformat);
}
static inline bool
-IsValidFBOTextureDepthStencilFormat(GLenum internalFormat)
+IsValidFBOTextureDepthStencilFormat(GLenum internalformat)
{
- return (
- internalFormat == LOCAL_GL_DEPTH_STENCIL ||
- internalFormat == LOCAL_GL_DEPTH24_STENCIL8);
+ return IsGLDepthStencilFormat(internalformat);
}
/* The following IsValidFBORenderbufferXXX functions check the internal
format that is stored by WebGLRenderbuffer::InternalFormat(). Valid
values can be found in WebGLContext::RenderbufferStorage. */
static inline bool
IsValidFBORenderbufferColorFormat(GLenum internalFormat)
{
@@ -325,17 +298,17 @@ WebGLFramebuffer::Attachment::IsComplete
{
return false;
}
if (Texture()) {
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
const WebGLTexture::ImageInfo& imageInfo =
Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
- GLenum internalformat = imageInfo.InternalFormat().get();
+ GLenum internalformat = imageInfo.EffectiveInternalFormat().get();
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
return IsValidFBOTextureDepthFormat(internalformat);
if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
return false; // Textures can't have the correct format for stencil buffers
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
--- a/dom/canvas/WebGLFramebuffer.h
+++ b/dom/canvas/WebGLFramebuffer.h
@@ -48,16 +48,18 @@ public:
explicit Attachment(FBAttachment aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
~Attachment();
bool IsDefined() const;
bool IsDeleteRequested() const;
+ TexInternalFormat EffectiveInternalFormat() const;
+
bool HasAlpha() const;
bool IsReadableFloat() const;
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
void SetRenderbuffer(WebGLRenderbuffer* rb);
const WebGLTexture* Texture() const {
return mTexturePtr;
new file mode 100644
--- /dev/null
+++ b/dom/canvas/WebGLInternalFormatsTable.h
@@ -0,0 +1,82 @@
+// intentionally no include guard here.
+
+#ifndef HANDLE_WEBGL_INTERNAL_FORMAT
+#error This header is meant to be included by other files defining HANDLE_WEBGL_INTERNAL_FORMAT.
+#endif
+
+#define WEBGL_INTERNAL_FORMAT(effectiveinternalformat, unsizedinternalformat, type) \
+ HANDLE_WEBGL_INTERNAL_FORMAT(LOCAL_GL_##effectiveinternalformat, \
+ LOCAL_GL_##unsizedinternalformat, \
+ LOCAL_GL_##type)
+
+// OpenGL ES 3.0.3, Table 3.2
+//
+// Maps effective internal formats to (unsized internal format, type) pairs.
+//
+// Effective int. fmt. Unsized int. fmt. Type
+WEBGL_INTERNAL_FORMAT(ALPHA8, ALPHA, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(LUMINANCE8, LUMINANCE, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(LUMINANCE8_ALPHA8, LUMINANCE_ALPHA, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RGB8, RGB, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RGBA4, RGBA, UNSIGNED_SHORT_4_4_4_4)
+WEBGL_INTERNAL_FORMAT(RGB5_A1, RGBA, UNSIGNED_SHORT_5_5_5_1)
+WEBGL_INTERNAL_FORMAT(RGBA8, RGBA, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RGB10_A2, RGB, UNSIGNED_INT_2_10_10_10_REV)
+WEBGL_INTERNAL_FORMAT(DEPTH_COMPONENT16, DEPTH_COMPONENT, UNSIGNED_SHORT)
+WEBGL_INTERNAL_FORMAT(DEPTH_COMPONENT24, DEPTH_COMPONENT, UNSIGNED_INT)
+WEBGL_INTERNAL_FORMAT(R8, RED, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RG8, RG, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(R16F, RED, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(R32F, RED, FLOAT)
+WEBGL_INTERNAL_FORMAT(RG16F, RG, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(RG32F, RG, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(R8I, RED_INTEGER, BYTE)
+WEBGL_INTERNAL_FORMAT(R8UI, RED_INTEGER, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(R16I, RED_INTEGER, BYTE)
+WEBGL_INTERNAL_FORMAT(R16UI, RED_INTEGER, UNSIGNED_SHORT)
+WEBGL_INTERNAL_FORMAT(R32I, RED_INTEGER, INT)
+WEBGL_INTERNAL_FORMAT(R32UI, RED_INTEGER, UNSIGNED_INT)
+WEBGL_INTERNAL_FORMAT(RG8I, RG_INTEGER, BYTE)
+WEBGL_INTERNAL_FORMAT(RG8UI, RG_INTEGER, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RG16I, RG_INTEGER, SHORT)
+WEBGL_INTERNAL_FORMAT(RG16UI, RG_INTEGER, UNSIGNED_SHORT)
+WEBGL_INTERNAL_FORMAT(RG32I, RG_INTEGER, INT)
+WEBGL_INTERNAL_FORMAT(RG32UI, RG_INTEGER, UNSIGNED_INT)
+WEBGL_INTERNAL_FORMAT(RGBA32F, RGBA, FLOAT)
+WEBGL_INTERNAL_FORMAT(RGB32F, RGB, FLOAT)
+WEBGL_INTERNAL_FORMAT(ALPHA32F_EXT, ALPHA, FLOAT)
+WEBGL_INTERNAL_FORMAT(LUMINANCE32F_EXT, LUMINANCE, FLOAT)
+WEBGL_INTERNAL_FORMAT(LUMINANCE_ALPHA32F_EXT, LUMINANCE_ALPHA, FLOAT)
+WEBGL_INTERNAL_FORMAT(RGBA16F, RGBA, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(RGB16F, RGB, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(ALPHA16F_EXT, ALPHA, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(LUMINANCE16F_EXT, LUMINANCE, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(LUMINANCE_ALPHA16F_EXT, LUMINANCE_ALPHA, HALF_FLOAT)
+WEBGL_INTERNAL_FORMAT(DEPTH24_STENCIL8, DEPTH_STENCIL, UNSIGNED_INT_24_8)
+WEBGL_INTERNAL_FORMAT(R11F_G11F_B10F, RGB, UNSIGNED_INT_10F_11F_11F_REV)
+WEBGL_INTERNAL_FORMAT(RGB9_E5, RGB, UNSIGNED_INT_5_9_9_9_REV)
+WEBGL_INTERNAL_FORMAT(SRGB8, SRGB, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(SRGB8_ALPHA8, SRGB_ALPHA, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(DEPTH_COMPONENT32F, DEPTH_COMPONENT, FLOAT)
+WEBGL_INTERNAL_FORMAT(DEPTH32F_STENCIL8, DEPTH_STENCIL, FLOAT_32_UNSIGNED_INT_24_8_REV)
+WEBGL_INTERNAL_FORMAT(RGB565, RGB, UNSIGNED_SHORT_5_6_5)
+WEBGL_INTERNAL_FORMAT(RGBA32UI, RGBA_INTEGER, UNSIGNED_INT)
+WEBGL_INTERNAL_FORMAT(RGB32UI, RGB_INTEGER, UNSIGNED_INT)
+WEBGL_INTERNAL_FORMAT(RGBA16UI, RGBA_INTEGER, UNSIGNED_SHORT)
+WEBGL_INTERNAL_FORMAT(RGB16UI, RGB_INTEGER, UNSIGNED_SHORT)
+WEBGL_INTERNAL_FORMAT(RGBA8UI, RGBA_INTEGER, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RGB8UI, RGB_INTEGER, UNSIGNED_BYTE)
+WEBGL_INTERNAL_FORMAT(RGBA32I, RGBA_INTEGER, INT)
+WEBGL_INTERNAL_FORMAT(RGB32I, RGB_INTEGER, INT)
+WEBGL_INTERNAL_FORMAT(RGBA16I, RGBA_INTEGER, SHORT)
+WEBGL_INTERNAL_FORMAT(RGB16I, RGB_INTEGER, SHORT)
+WEBGL_INTERNAL_FORMAT(RGBA8I, RGBA_INTEGER, BYTE)
+WEBGL_INTERNAL_FORMAT(RGB8I, RGB_INTEGER, BYTE)
+WEBGL_INTERNAL_FORMAT(R8_SNORM, RED, BYTE)
+WEBGL_INTERNAL_FORMAT(RG8_SNORM, RG, BYTE)
+WEBGL_INTERNAL_FORMAT(RGB8_SNORM, RGB, BYTE)
+WEBGL_INTERNAL_FORMAT(RGBA8_SNORM, RGBA, BYTE)
+WEBGL_INTERNAL_FORMAT(RGB10_A2UI, RGBA_INTEGER, UNSIGNED_INT_2_10_10_10_REV)
+
+#undef WEBGL_INTERNAL_FORMAT
+#undef HANDLE_WEBGL_INTERNAL_FORMAT
--- a/dom/canvas/WebGLStrongTypes.h
+++ b/dom/canvas/WebGLStrongTypes.h
@@ -294,16 +294,19 @@ STRONG_GLENUM_END(TexFormat)
STRONG_GLENUM_BEGIN(TexInternalFormat)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(DEPTH_COMPONENT),
STRONG_GLENUM_VALUE(ALPHA),
STRONG_GLENUM_VALUE(RGB),
STRONG_GLENUM_VALUE(RGBA),
STRONG_GLENUM_VALUE(LUMINANCE),
STRONG_GLENUM_VALUE(LUMINANCE_ALPHA),
+ STRONG_GLENUM_VALUE(ALPHA8),
+ STRONG_GLENUM_VALUE(LUMINANCE8),
+ STRONG_GLENUM_VALUE(LUMINANCE8_ALPHA8),
STRONG_GLENUM_VALUE(RGB8),
STRONG_GLENUM_VALUE(RGBA4),
STRONG_GLENUM_VALUE(RGB5_A1),
STRONG_GLENUM_VALUE(RGBA8),
STRONG_GLENUM_VALUE(RGB10_A2),
STRONG_GLENUM_VALUE(DEPTH_COMPONENT16),
STRONG_GLENUM_VALUE(DEPTH_COMPONENT24),
STRONG_GLENUM_VALUE(R8),
@@ -327,18 +330,24 @@ STRONG_GLENUM_BEGIN(TexInternalFormat)
STRONG_GLENUM_VALUE(COMPRESSED_RGB_S3TC_DXT1_EXT),
STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT1_EXT),
STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT3_EXT),
STRONG_GLENUM_VALUE(COMPRESSED_RGBA_S3TC_DXT5_EXT),
STRONG_GLENUM_VALUE(DEPTH_STENCIL),
STRONG_GLENUM_VALUE(ATC_RGBA_INTERPOLATED_ALPHA),
STRONG_GLENUM_VALUE(RGBA32F),
STRONG_GLENUM_VALUE(RGB32F),
+ STRONG_GLENUM_VALUE(ALPHA32F_EXT),
+ STRONG_GLENUM_VALUE(LUMINANCE32F_EXT),
+ STRONG_GLENUM_VALUE(LUMINANCE_ALPHA32F_EXT),
STRONG_GLENUM_VALUE(RGBA16F),
STRONG_GLENUM_VALUE(RGB16F),
+ STRONG_GLENUM_VALUE(ALPHA16F_EXT),
+ STRONG_GLENUM_VALUE(LUMINANCE16F_EXT),
+ STRONG_GLENUM_VALUE(LUMINANCE_ALPHA16F_EXT),
STRONG_GLENUM_VALUE(DEPTH24_STENCIL8),
STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_4BPPV1),
STRONG_GLENUM_VALUE(COMPRESSED_RGB_PVRTC_2BPPV1),
STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_4BPPV1),
STRONG_GLENUM_VALUE(COMPRESSED_RGBA_PVRTC_2BPPV1),
STRONG_GLENUM_VALUE(R11F_G11F_B10F),
STRONG_GLENUM_VALUE(RGB9_E5),
STRONG_GLENUM_VALUE(SRGB),
--- a/dom/canvas/WebGLTexture.cpp
+++ b/dom/canvas/WebGLTexture.cpp
@@ -47,17 +47,17 @@ WebGLTexture::Delete() {
mContext->gl->fDeleteTextures(1, &mGLName);
LinkedListElement<WebGLTexture>::removeFrom(mContext->mTextures);
}
int64_t
WebGLTexture::ImageInfo::MemoryUsage() const {
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
return 0;
- int64_t bitsPerTexel = WebGLContext::GetBitsPerTexel(mInternalFormat, mType);
+ int64_t bitsPerTexel = GetBitsPerTexel(mEffectiveInternalFormat);
return int64_t(mWidth) * int64_t(mHeight) * bitsPerTexel/8;
}
int64_t
WebGLTexture::MemoryUsage() const {
if (IsDeleted())
return 0;
int64_t result = 0;
@@ -133,26 +133,25 @@ WebGLTexture::Bind(TexTarget aTexTarget)
if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES())
mContext->gl->fTexParameteri(aTexTarget.get(), LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
}
}
void
WebGLTexture::SetImageInfo(TexImageTarget aTexImageTarget, GLint aLevel,
GLsizei aWidth, GLsizei aHeight,
- TexInternalFormat aInternalFormat, TexType aType,
- WebGLImageDataStatus aStatus)
+ TexInternalFormat aEffectiveInternalFormat, WebGLImageDataStatus aStatus)
{
MOZ_ASSERT(TexImageTargetToTexTarget(aTexImageTarget) == mTarget);
if (TexImageTargetToTexTarget(aTexImageTarget) != mTarget)
return;
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
- ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aInternalFormat, aType, aStatus);
+ ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aEffectiveInternalFormat, aStatus);
if (aLevel > 0)
SetCustomMipmap();
// Invalidate framebuffer status cache
NotifyFBsStatusChanged();
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
@@ -324,17 +323,19 @@ WebGLTexture::ResolvedFakeBlackStatus()
mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
"with some level 0 image having width or height not a power of two, and with a wrap mode "
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
}
}
- if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
+ TexType type = TypeFromInternalFormat(ImageInfoBase().mEffectiveInternalFormat);
+
+ if (type == LOCAL_GL_FLOAT &&
!Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_float_linear))
{
if (mMinFilter == LOCAL_GL_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
{
mContext->GenerateWarning("%s is a texture with a linear minification filter, "
@@ -344,17 +345,17 @@ WebGLTexture::ResolvedFakeBlackStatus()
}
else if (mMagFilter == LOCAL_GL_LINEAR)
{
mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
"which is not compatible with gl.FLOAT by default. "
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
}
- } else if (ImageInfoBase().mType == LOCAL_GL_HALF_FLOAT_OES &&
+ } else if (type == LOCAL_GL_HALF_FLOAT &&
!Context()->IsExtensionEnabled(WebGLExtensionID::OES_texture_half_float_linear))
{
if (mMinFilter == LOCAL_GL_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
{
mContext->GenerateWarning("%s is a texture with a linear minification filter, "
@@ -529,47 +530,49 @@ void
WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint level)
{
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
mContext->MakeContextCurrent();
// Try to clear with glCLear.
- TexInternalFormat internalformat = imageInfo.mInternalFormat;
- TexType type = imageInfo.mType;
- WebGLTexelFormat texelformat = GetWebGLTexelFormat(internalformat, type);
bool cleared = ClearWithTempFB(mContext, GLName(),
imageTarget, level,
- internalformat, imageInfo.mHeight, imageInfo.mWidth);
+ imageInfo.mEffectiveInternalFormat,
+ imageInfo.mHeight, imageInfo.mWidth);
if (cleared) {
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
return;
}
// That didn't work. Try uploading zeros then.
gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget.get());
- uint32_t texelsize = WebGLTexelConversions::TexelBytesForFormat(texelformat);
+ size_t bitspertexel = GetBitsPerTexel(imageInfo.mEffectiveInternalFormat);
+ MOZ_ASSERT((bitspertexel % 8) == 0); // that would only happen for compressed images, which
+ // cannot use deferred initialization.
+ size_t bytespertexel = bitspertexel / 8;
CheckedUint32 checked_byteLength
= WebGLContext::GetImageSize(
imageInfo.mHeight,
imageInfo.mWidth,
- texelsize,
+ bytespertexel,
mContext->mPixelStoreUnpackAlignment);
MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier
ScopedFreePtr<void> zeros;
zeros = calloc(1, checked_byteLength.value());
gl::GLContext* gl = mContext->gl;
- GLenum driverType = DriverTypeFromType(gl, type);
GLenum driverInternalFormat = LOCAL_GL_NONE;
GLenum driverFormat = LOCAL_GL_NONE;
- DriverFormatsFromFormatAndType(gl, internalformat, type, &driverInternalFormat, &driverFormat);
+ GLenum driverType = LOCAL_GL_NONE;
+ DriverFormatsFromEffectiveInternalFormat(gl, imageInfo.mEffectiveInternalFormat,
+ &driverInternalFormat, &driverFormat, &driverType);
mContext->GetAndFlushUnderlyingGLErrors();
gl->fTexImage2D(imageTarget.get(), level, driverInternalFormat,
imageInfo.mWidth, imageInfo.mHeight,
0, driverFormat, driverType,
zeros);
GLenum error = mContext->GetAndFlushUnderlyingGLErrors();
if (error) {
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -62,41 +62,37 @@ protected:
public:
class ImageInfo
: public WebGLRectangleObject
{
public:
ImageInfo()
- : mInternalFormat(LOCAL_GL_NONE)
- , mType(LOCAL_GL_NONE)
+ : mEffectiveInternalFormat(LOCAL_GL_NONE)
, mImageDataStatus(WebGLImageDataStatus::NoImageData)
{}
ImageInfo(GLsizei width,
GLsizei height,
- TexInternalFormat internalFormat,
- TexType type,
+ TexInternalFormat effectiveInternalFormat,
WebGLImageDataStatus status)
: WebGLRectangleObject(width, height)
- , mInternalFormat(internalFormat)
- , mType(type)
+ , mEffectiveInternalFormat(effectiveInternalFormat)
, mImageDataStatus(status)
{
// shouldn't use this constructor to construct a null ImageInfo
MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
}
bool operator==(const ImageInfo& a) const {
return mImageDataStatus == a.mImageDataStatus &&
mWidth == a.mWidth &&
mHeight == a.mHeight &&
- mInternalFormat == a.mInternalFormat &&
- mType == a.mType;
+ mEffectiveInternalFormat == a.mEffectiveInternalFormat;
}
bool operator!=(const ImageInfo& a) const {
return !(*this == a);
}
bool IsSquare() const {
return mWidth == mHeight;
}
bool IsPositive() const {
@@ -105,31 +101,27 @@ public:
bool IsPowerOfTwo() const {
return is_pot_assuming_nonnegative(mWidth) &&
is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
}
bool HasUninitializedImageData() const {
return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
}
int64_t MemoryUsage() const;
- /*! This is the format passed from JS to WebGL.
- * It can be converted to a value to be passed to driver with
- * DriverFormatsFromFormatAndType().
- */
- TexInternalFormat InternalFormat() const { return mInternalFormat; }
- /*! This is the type passed from JS to WebGL.
- * It can be converted to a value to be passed to driver with
- * DriverTypeFromType().
- */
- TexType Type() const { return mType; }
+ TexInternalFormat EffectiveInternalFormat() const { return mEffectiveInternalFormat; }
protected:
- TexInternalFormat mInternalFormat; //!< This is the WebGL/GLES internal format.
- TexType mType; //!< This is the WebGL/GLES type
+ /*
+ * This is the "effective internal format" of the texture,
+ * an official OpenGL spec concept, see
+ * OpenGL ES 3.0.3 spec, section 3.8.3, page 126 and below.
+ */
+ TexInternalFormat mEffectiveInternalFormat;
+
WebGLImageDataStatus mImageDataStatus;
friend class WebGLTexture;
};
private:
static size_t FaceForTarget(TexImageTarget texImageTarget) {
if (texImageTarget == LOCAL_GL_TEXTURE_2D)
@@ -225,18 +217,17 @@ protected:
bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const;
public:
void Bind(TexTarget aTexTarget);
void SetImageInfo(TexImageTarget aTarget, GLint aLevel,
GLsizei aWidth, GLsizei aHeight,
- TexInternalFormat aInternalFormat, TexType aType,
- WebGLImageDataStatus aStatus);
+ TexInternalFormat aFormat, WebGLImageDataStatus aStatus);
void SetMinFilter(TexMinFilter aMinFilter) {
mMinFilter = aMinFilter;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}
void SetMagFilter(TexMagFilter aMagFilter) {
mMagFilter = aMagFilter;
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2360,17 +2360,16 @@ bool
GLContext::ResizeScreenBuffer(const IntSize& size)
{
if (!IsOffscreenSizeAllowed(size))
return false;
return mScreen->Resize(size);
}
-
void
GLContext::DestroyScreenBuffer()
{
mScreen = nullptr;
}
void
GLContext::ForceDirtyScreen()