WebGL2: Support non-power-of-two textures. (bug 1080921, r=jgilbert).

--HG--
extra : rebase_source : 6d948f27ec14cea54211f62dc0dc813419eb5151
This commit is contained in:
David Anderson 2014-10-14 19:10:15 -07:00
parent f15da1a3dd
commit e290f953ea
5 changed files with 27 additions and 22 deletions

View File

@ -292,7 +292,7 @@ WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
tex->EnsureNoUninitializedImageData(texImageTarget, level);
}
}

View File

@ -453,7 +453,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
tex->SetImageInfo(texImageTarget, level, width, height, 1,
effectiveInternalFormat,
WebGLImageDataStatus::UninitializedImageData);
tex->DoDeferredImageInitialization(texImageTarget, level);
tex->EnsureNoUninitializedImageData(texImageTarget, level);
}
// if we are completely outside of the framebuffer, we can exit now with our black texture
@ -601,7 +601,7 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
tex->EnsureNoUninitializedImageData(texImageTarget, level);
}
}
@ -927,7 +927,7 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
}
if (!tex->IsFirstImagePowerOfTwo())
if (!IsWebGL2() && !tex->IsFirstImagePowerOfTwo())
return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
TexInternalFormat internalformat = tex->ImageInfoAt(imageTarget, 0).EffectiveInternalFormat();
@ -3436,7 +3436,7 @@ WebGLContext::CompressedTexSubImage2D(GLenum rawTexImgTarget, GLint level, GLint
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
tex->EnsureNoUninitializedImageData(texImageTarget, level);
}
}
@ -3972,7 +3972,7 @@ WebGLContext::TexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
if (coversWholeImage) {
tex->SetImageDataStatus(texImageTarget, level, WebGLImageDataStatus::InitializedImageData);
} else {
tex->DoDeferredImageInitialization(texImageTarget, level);
tex->EnsureNoUninitializedImageData(texImageTarget, level);
}
}
MakeContextCurrent();

View File

@ -816,8 +816,10 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
* "If level is greater than zero, and either width or
* height is not a power-of-two, the error INVALID_VALUE is
* generated."
*
* This restriction does not apply to GL ES Version 3.0+.
*/
if (level > 0) {
if (!IsWebGL2() && level > 0) {
if (!is_pot_assuming_nonnegative(width)) {
ErrorInvalidValue("%s: level >= 0, width of %d must be a power of two.",
InfoFrom(func, dims), width);
@ -839,7 +841,7 @@ WebGLContext::ValidateTexImageSize(TexImageTarget texImageTarget, GLint level,
return false;
}
if (depth > 0 && !is_pot_assuming_nonnegative(depth)) {
if (!IsWebGL2() && !is_pot_assuming_nonnegative(depth)) {
ErrorInvalidValue("%s: level >= 0, depth of %d must be a power of two.",
InfoFrom(func, dims), depth);
return false;

View File

@ -186,11 +186,12 @@ WebGLTexture::SetCustomMipmap() {
// since we were in GeneratedMipmap mode, we know that the level 0 images all have the same info,
// and are power-of-two.
ImageInfo imageInfo = ImageInfoAtFace(0, 0);
NS_ASSERTION(imageInfo.IsPowerOfTwo(), "this texture is NPOT, so how could GenerateMipmap() ever accept it?");
NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(),
"this texture is NPOT, so how could GenerateMipmap() ever accept it?");
GLsizei size = std::max(std::max(imageInfo.mWidth, imageInfo.mHeight), imageInfo.mDepth);
// so, the size is a power of two, let's find its log in base 2.
// Find floor(log2(size)). (ES 3.0.4, 3.8 - Mipmapping).
size_t maxLevel = 0;
for (GLsizei n = size; n > 1; n >>= 1)
++maxLevel;
@ -198,7 +199,6 @@ WebGLTexture::SetCustomMipmap() {
EnsureMaxLevelWithCustomImagesAtLeast(maxLevel);
for (size_t level = 1; level <= maxLevel; ++level) {
// again, since the sizes are powers of two, no need for any max(1,x) computation
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
@ -285,7 +285,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
("%s is a %dD texture, with a minification filter requiring a mipmap, "
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black, dim);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!ImageInfoBase().IsPowerOfTwo()) {
} else if (!mContext->IsWebGL2() && !ImageInfoBase().IsPowerOfTwo()) {
mContext->GenerateWarning
("%s is a %dD texture, with a minification filter requiring a mipmap, "
"and either its width or height is not a power of two.", msg_rendering_as_black);
@ -299,7 +299,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
("%s is a %dD texture and its width or height is equal to zero.",
msg_rendering_as_black, dim);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoBase().IsPowerOfTwo()) {
} else if (!AreBothWrapModesClampToEdge() && !mContext->IsWebGL2() && !ImageInfoBase().IsPowerOfTwo()) {
mContext->GenerateWarning
("%s is a %dD texture, with a minification filter not requiring a mipmap, "
"with its width or height not a power of two, and with a wrap mode "
@ -310,9 +310,11 @@ WebGLTexture::ResolvedFakeBlackStatus() {
}
else // cube map
{
bool areAllLevel0ImagesPOT = true;
for (size_t face = 0; face < mFacesCount; ++face)
areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
bool legalImageSize = true;
if (!mContext->IsWebGL2()) {
for (size_t face = 0; face < mFacesCount; ++face)
legalImageSize &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
}
if (DoesMinFilterRequireMipmap())
{
@ -321,7 +323,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
"and is not mipmap cube complete (as defined in section 3.7.10).",
msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!areAllLevel0ImagesPOT) {
} else if (!legalImageSize) {
mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
"and either the width or the height of some level 0 image is not a power of two.",
msg_rendering_as_black);
@ -335,7 +337,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
"and is not cube complete (as defined in section 3.7.10).",
msg_rendering_as_black);
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
} else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
} else if (!AreBothWrapModesClampToEdge() && !legalImageSize) {
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);
@ -422,7 +424,7 @@ WebGLTexture::ResolvedFakeBlackStatus() {
TexImageTarget imageTarget = TexImageTargetForTargetAndFace(mTarget, face);
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) {
DoDeferredImageInitialization(imageTarget, level);
EnsureNoUninitializedImageData(imageTarget, level);
}
}
}
@ -542,10 +544,11 @@ ClearWithTempFB(WebGLContext* context, GLuint tex,
void
WebGLTexture::DoDeferredImageInitialization(TexImageTarget imageTarget, GLint level)
WebGLTexture::EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint level)
{
const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
if (!imageInfo.HasUninitializedImageData())
return;
mContext->MakeContextCurrent();

View File

@ -199,7 +199,7 @@ public:
imageInfo.mImageDataStatus = newStatus;
}
void DoDeferredImageInitialization(TexImageTarget imageTarget, GLint level);
void EnsureNoUninitializedImageData(TexImageTarget imageTarget, GLint level);
protected: