Bug 1077183 - Untangle the confusion between effective and unsized internalformats in the WebGL implementation - r=jgilbert

This commit is contained in:
Benoit Jacob 2014-10-07 19:52:58 -04:00
parent efd9df19a5
commit 9fc8a1b4bc
15 changed files with 622 additions and 566 deletions

View File

@ -153,16 +153,9 @@ WebGL2Context::TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat
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);

View File

@ -1760,6 +1760,13 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
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;
@ -1807,8 +1814,11 @@ bool WebGLContext::TexImageFromVideoElement(const TexImageTarget texImageTarget,
}
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;

View File

@ -94,7 +94,7 @@ namespace gfx {
class SourceSurface;
}
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format, TexType type);
WebGLTexelFormat GetWebGLTexelFormat(TexInternalFormat format);
void AssertUintParamCorrect(gl::GLContext* gl, GLenum pname, GLuint shadow);
@ -490,9 +490,6 @@ public:
const TexImageTarget texImageTarget(rawTexImgTarget);
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
return;
if (level < 0)
return ErrorInvalidValue("texImage2D: level is negative");
@ -560,9 +557,6 @@ public:
const TexImageTarget texImageTarget(rawTexImageTarget);
if (!ValidateTexImageFormatAndType(format, type, WebGLTexImageFunc::TexImage))
return;
if (level < 0)
return ErrorInvalidValue("texSubImage2D: level is negative");
@ -575,7 +569,7 @@ public:
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,
@ -1145,8 +1139,6 @@ protected:
GLsizei width, GLsizei height,
uint32_t byteLength, WebGLTexImageFunc func);
static uint32_t GetBitsPerTexel(TexInternalFormat format, TexType type);
void Invalidate();
void DestroyResourcesAndContext();
@ -1203,7 +1195,7 @@ protected:
void CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level,
GLenum internalformat,
TexInternalFormat internalformat,
GLint xoffset,
GLint yoffset,
GLint x,

View File

@ -676,7 +676,7 @@ WebGLContext::BindFakeBlackTexturesHelper(
}
bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().InternalFormat());
FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().EffectiveInternalFormat());
UniquePtr<FakeBlackTexture>&
blackTexturePtr = alpha
? transparentTextureScopedPtr

View File

@ -354,7 +354,7 @@ WebGLContext::CheckFramebufferStatus(GLenum target)
void
WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
GLint level,
GLenum internalformat,
TexInternalFormat internalformat,
GLint xoffset,
GLint yoffset,
GLint x,
@ -372,7 +372,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
// 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,
@ -382,7 +382,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
return;
}
if (!ValidateCopyTexImage(internalformat, func))
if (!ValidateCopyTexImage(internalformat.get(), func))
return;
if (!mBoundFramebuffer)
@ -401,50 +401,50 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
}
}
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
@ -468,6 +468,20 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
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
@ -504,37 +518,7 @@ WebGLContext::CopyTexImage2D(GLenum rawTexImgTarget,
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
@ -602,7 +586,11 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
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);
}
@ -922,7 +910,7 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
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.");
@ -1183,12 +1171,17 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
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;
@ -1224,9 +1217,10 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
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:
@ -1235,7 +1229,7 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
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:
@ -3353,7 +3347,7 @@ WebGLContext::CompressedTexImage2D(GLenum rawTexImgTarget,
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);
}
@ -3387,7 +3381,7 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
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");
}
@ -3599,7 +3593,7 @@ WebGLContext::GetShaderTranslatedSource(WebGLShader *shader, nsAString& retval)
GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget,
GLint level,
TexInternalFormat internalFormat,
TexInternalFormat internalformat,
GLsizei width,
GLsizei height,
GLint border,
@ -3610,20 +3604,26 @@ GLenum WebGLContext::CheckedTexImage2D(TexImageTarget texImageTarget,
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();
@ -3652,6 +3652,10 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
{
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,
@ -3674,7 +3678,14 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
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);
@ -3712,8 +3723,10 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
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;
@ -3752,7 +3765,8 @@ WebGLContext::TexImage2D_base(TexImageTarget texImageTarget, GLint level,
// 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
@ -3830,14 +3844,28 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
{
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");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat internalformat = imageInfo.InternalFormat();
if (!ValidateTexImage(2, texImageTarget, level, internalformat.get(),
if (!tex->HasImageInfoAt(texImageTarget, level)) {
return ErrorInvalidOperation("texSubImage2D: no previously defined texture image");
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
const TexInternalFormat existingEffectiveInternalFormat = imageInfo.EffectiveInternalFormat();
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))
@ -3848,11 +3876,11 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
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);
@ -3882,7 +3910,7 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint 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();
@ -3906,10 +3934,14 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
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);
}
@ -4066,119 +4098,37 @@ BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize)
}
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

View File

@ -31,29 +31,28 @@ 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
@ -76,11 +75,12 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
}
}
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:
@ -117,152 +117,277 @@ 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;
// driverFormat: always just the unsized internalformat that we just got
GLenum driverFormat = unsizedinternalformat.get();
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;
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;
if (gl->IsGLES())
return type;
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;
// 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_ALPHA8:
case LOCAL_GL_LUMINANCE8:
case LOCAL_GL_R8:
case LOCAL_GL_R8I:
case LOCAL_GL_R8UI:
case LOCAL_GL_R8_SNORM:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
case LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA:
case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
return 8;
case LOCAL_GL_LUMINANCE8_ALPHA8:
case LOCAL_GL_RGBA4:
case LOCAL_GL_RGB5_A1:
case LOCAL_GL_DEPTH_COMPONENT16:
case LOCAL_GL_RG8:
case LOCAL_GL_R16I:
case LOCAL_GL_R16UI:
case LOCAL_GL_RGB565:
case LOCAL_GL_R16F:
case LOCAL_GL_RG8I:
case LOCAL_GL_RG8UI:
case LOCAL_GL_RG8_SNORM:
case LOCAL_GL_ALPHA16F_EXT:
case LOCAL_GL_LUMINANCE16F_EXT:
return 16;
case LOCAL_GL_RGB8:
case LOCAL_GL_DEPTH_COMPONENT24:
case LOCAL_GL_SRGB8:
case LOCAL_GL_RGB8UI:
case LOCAL_GL_RGB8I:
case LOCAL_GL_RGB8_SNORM:
return 24;
case LOCAL_GL_RGBA8:
case LOCAL_GL_RGB10_A2:
case LOCAL_GL_R32F:
case LOCAL_GL_RG16F:
case LOCAL_GL_R32I:
case LOCAL_GL_R32UI:
case LOCAL_GL_RG16I:
case LOCAL_GL_RG16UI:
case LOCAL_GL_DEPTH24_STENCIL8:
case LOCAL_GL_R11F_G11F_B10F:
case LOCAL_GL_RGB9_E5:
case LOCAL_GL_SRGB8_ALPHA8:
case LOCAL_GL_DEPTH_COMPONENT32F:
case LOCAL_GL_RGBA8UI:
case LOCAL_GL_RGBA8I:
case LOCAL_GL_RGBA8_SNORM:
case LOCAL_GL_RGB10_A2UI:
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
case LOCAL_GL_ALPHA32F_EXT:
case LOCAL_GL_LUMINANCE32F_EXT:
return 32;
case LOCAL_GL_DEPTH32F_STENCIL8:
return 40;
case LOCAL_GL_RGB16F:
case LOCAL_GL_RGB16UI:
case LOCAL_GL_RGB16I:
return 48;
case LOCAL_GL_RG32F:
case LOCAL_GL_RG32I:
case LOCAL_GL_RG32UI:
case LOCAL_GL_RGBA16F:
case LOCAL_GL_RGBA16UI:
case LOCAL_GL_RGBA16I:
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
return 64;
case LOCAL_GL_RGB32F:
case LOCAL_GL_RGB32UI:
case LOCAL_GL_RGB32I:
return 96;
case LOCAL_GL_RGBA32F:
case LOCAL_GL_RGBA32UI:
case LOCAL_GL_RGBA32I:
return 128;
default:
MOZ_ASSERT(false, "Unhandled format");
return 0;
}
return type;
}
void

View File

@ -16,9 +16,28 @@ 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, ...

View File

@ -673,7 +673,7 @@ WebGLContext::ValidateTexImageType(GLenum type,
}
/* 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",
@ -1025,95 +1025,6 @@ WebGLContext::ValidateTexSubImageSize(GLint xoffset, GLint yoffset, GLint /*zoff
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.
@ -1141,7 +1052,6 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format,
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;
@ -1150,7 +1060,6 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format,
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;
@ -1160,7 +1069,6 @@ WebGLContext::ValidateTexImageFormatAndType(GLenum format,
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;
@ -1291,7 +1199,6 @@ WebGLContext::ValidateTexInputData(GLenum type, int jsArrayType, WebGLTexImageFu
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:
@ -1449,6 +1356,7 @@ WebGLContext::ValidateTexImage(GLuint dims, TexImageTarget texImageTarget,
}
const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(texImageTarget, level);
if (!ValidateTexSubImageSize(xoffset, yoffset, zoffset,
width, height, depth,
imageInfo.Width(), imageInfo.Height(), 0,

View File

@ -79,7 +79,7 @@ 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;
@ -96,7 +96,7 @@ WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& att
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())
@ -105,37 +105,30 @@ WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& att
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
@ -230,7 +223,7 @@ WebGLFramebuffer::Attachment::RectangleObject() const
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
@ -239,46 +232,26 @@ IsValidFBOTextureColorFormat(GLenum internalFormat)
* 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
@ -330,7 +303,7 @@ WebGLFramebuffer::Attachment::IsComplete() const
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);

View File

@ -53,6 +53,8 @@ public:
bool IsDeleteRequested() const;
TexInternalFormat EffectiveInternalFormat() const;
bool HasAlpha() const;
bool IsReadableFloat() const;

View File

@ -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

View File

@ -299,6 +299,9 @@ STRONG_GLENUM_BEGIN(TexInternalFormat)
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),
@ -332,8 +335,14 @@ STRONG_GLENUM_BEGIN(TexInternalFormat)
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),

View File

@ -52,7 +52,7 @@ 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;
}
@ -138,8 +138,7 @@ WebGLTexture::Bind(TexTarget aTexTarget) {
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)
@ -147,7 +146,7 @@ WebGLTexture::SetImageInfo(TexImageTarget aTexImageTarget, GLint aLevel,
EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aInternalFormat, aType, aStatus);
ImageInfoAt(aTexImageTarget, aLevel) = ImageInfo(aWidth, aHeight, aEffectiveInternalFormat, aStatus);
if (aLevel > 0)
SetCustomMipmap();
@ -329,7 +328,9 @@ WebGLTexture::ResolvedFakeBlackStatus() {
}
}
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 ||
@ -349,7 +350,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
"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 ||
@ -534,13 +535,11 @@ WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint le
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;
@ -549,22 +548,26 @@ WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint le
// 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,

View File

@ -67,19 +67,16 @@ public:
{
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
@ -90,8 +87,7 @@ public:
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);
@ -110,21 +106,17 @@ public:
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;
@ -230,8 +222,7 @@ public:
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;

View File

@ -2365,7 +2365,6 @@ GLContext::ResizeScreenBuffer(const IntSize& size)
return mScreen->Resize(size);
}
void
GLContext::DestroyScreenBuffer()
{