Bug 591084 - various WebGLTexture improvements - r=vladimir

This commit is contained in:
Benoit Jacob 2010-09-02 10:29:41 -04:00
parent 970240fc6f
commit 705b0dc1a4
3 changed files with 56 additions and 30 deletions

View File

@ -685,7 +685,7 @@ public:
mFacesCount(0),
mMaxLevelWithCustomImages(0),
mHaveGeneratedMipmap(PR_FALSE),
mFakeBlackStatus(DontKnowIfNeedFakeBlack)
mFakeBlackStatus(DoNotNeedFakeBlack)
{}
void Delete() {
@ -913,12 +913,13 @@ public:
mHaveGeneratedMipmap = PR_FALSE;
}
PRBool IsGenerateMipmapAllowed() const {
const ImageInfo &first = ImageInfoAt(0, 0);
if (!first.IsPowerOfTwo())
return PR_FALSE;
for (size_t face = 0; face < mFacesCount; ++face) {
if (ImageInfoAt(0, face) != first)
PRBool IsFirstImagePowerOfTwo() const {
return ImageInfoAt(0, 0).IsPowerOfTwo();
}
PRBool AreAllLevel0ImageInfosEqual() const {
for (size_t face = 1; face < mFacesCount; ++face) {
if (ImageInfoAt(0, face) != ImageInfoAt(0, 0))
return PR_FALSE;
}
return PR_TRUE;
@ -927,7 +928,7 @@ public:
PRBool IsMipmapTexture2DComplete() const {
if (mTarget != LOCAL_GL_TEXTURE_2D)
return PR_FALSE;
if (!mImageInfos[0].IsPositive())
if (!ImageInfoAt(0, 0).IsPositive())
return PR_FALSE;
if (mHaveGeneratedMipmap)
return PR_TRUE;
@ -940,11 +941,7 @@ public:
const ImageInfo &first = ImageInfoAt(0, 0);
if (!first.IsPositive() || !first.IsSquare())
return PR_FALSE;
for (size_t face = 0; face < mFacesCount; ++face) {
if (ImageInfoAt(0, face) != first)
return PR_FALSE;
}
return PR_TRUE;
return AreAllLevel0ImageInfosEqual();
}
PRBool IsMipmapCubeComplete() const {
@ -966,26 +963,39 @@ public:
// Determine if the texture needs to be faked as a black texture.
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
const char *msg_rendering_as_black
= "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
"because it";
if (mTarget == LOCAL_GL_TEXTURE_2D)
{
if (DoesMinFilterRequireMipmap())
{
if (!IsMipmapTexture2DComplete() ||
!mImageInfos[0].IsPowerOfTwo())
{
if (!IsMipmapTexture2DComplete()) {
mContext->LogMessage("%s is a 2D texture, with a minification filter requiring a mipmap, "
"and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
} else if (!ImageInfoAt(0, 0).IsPowerOfTwo()) {
mContext->LogMessage("%s is a 2D texture, with a minification filter requiring a mipmap, "
"and either its width or height is not a power of two.", msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
}
}
else // no mipmap required
{
if (!mImageInfos[0].IsPositive() ||
(!AreBothWrapModesClampToEdge() && !mImageInfos[0].IsPowerOfTwo()))
{
if (!ImageInfoAt(0, 0).IsPositive()) {
mContext->LogMessage("%s is a 2D texture and its width or height is equal to zero.",
msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(0, 0).IsPowerOfTwo()) {
mContext->LogMessage("%s is a 2D texture, with a minification filter not requiring a mipmap, "
"with its width or height not a power of two, and with a wrap mode "
"different from CLAMP_TO_EDGE.", msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
}
}
}
else if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP)
else // cube map
{
PRBool areAllLevel0ImagesPOT = PR_TRUE;
for (size_t face = 0; face < mFacesCount; ++face)
@ -993,17 +1003,29 @@ public:
if (DoesMinFilterRequireMipmap())
{
if (!IsMipmapCubeComplete() ||
!areAllLevel0ImagesPOT)
{
if (!IsMipmapCubeComplete()) {
mContext->LogMessage("%s is a cube map texture, with a minification filter requiring a mipmap, "
"and is not mipmap cube complete (as defined in section 3.7.10).",
msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
} else if (!areAllLevel0ImagesPOT) {
mContext->LogMessage("%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);
mFakeBlackStatus = DoNeedFakeBlack;
}
}
else // no mipmap required
{
if (!IsCubeComplete() ||
(!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT))
{
if (!IsCubeComplete()) {
mContext->LogMessage("%s is a cube map texture, with a minification filter not requiring a mipmap, "
"and is not cube complete (as defined in section 3.7.10).",
msg_rendering_as_black);
mFakeBlackStatus = DoNeedFakeBlack;
} else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
mContext->LogMessage("%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 = DoNeedFakeBlack;
}
}

View File

@ -1254,8 +1254,12 @@ WebGLContext::GenerateMipmap(WebGLenum target)
if (!tex)
return ErrorInvalidOperation("generateMipmap: no texture is bound to this target");
if (!tex->IsGenerateMipmapAllowed()) {
return ErrorInvalidOperation("generateMipmap: texture does not satisfy requirements for generateMipmap");
if (!tex->IsFirstImagePowerOfTwo()) {
return ErrorInvalidOperation("generateMipmap: the width or height of this texture is not a power of two");
}
if (!tex->AreAllLevel0ImageInfosEqual()) {
return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type.");
}
tex->SetGeneratedMipmap();

View File

@ -213,11 +213,11 @@ WebGLContext::LogMessage(const char *fmt, ...)
void
WebGLContext::LogMessage(const char *fmt, va_list ap)
{
char buf[256];
char buf[1024];
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (console) {
PR_vsnprintf(buf, 256, fmt, ap);
PR_vsnprintf(buf, 1024, fmt, ap);
console->LogStringMessage(NS_ConvertUTF8toUTF16(nsDependentCString(buf)).get());
fprintf(stderr, "%s\n", buf);
}