зеркало из https://github.com/mozilla/gecko-dev.git
Bug 922810 - Part 2: reorganize the tracking of fake back statuses - r=jgilbert
This commit is contained in:
Родитель
8e13af6dbf
Коммит
0f916f5f9f
|
@ -122,7 +122,7 @@ WebGLContext::WebGLContext()
|
|||
mShaderValidation = true;
|
||||
|
||||
mBlackTexturesAreInitialized = false;
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::Unknown;
|
||||
|
||||
mVertexAttrib0Vector[0] = 0;
|
||||
mVertexAttrib0Vector[1] = 0;
|
||||
|
|
|
@ -798,11 +798,13 @@ private:
|
|||
// -----------------------------------------------------------------------------
|
||||
// PROTECTED
|
||||
protected:
|
||||
void SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) {
|
||||
mFakeBlackStatus = x;
|
||||
}
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLContextFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
|
||||
bool NeedFakeBlack();
|
||||
void BindFakeBlackTextures();
|
||||
void UnbindFakeBlackTextures();
|
||||
|
||||
|
@ -1090,7 +1092,7 @@ protected:
|
|||
uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
|
||||
bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
|
||||
|
||||
FakeBlackStatus mFakeBlackStatus;
|
||||
WebGLContextFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
GLuint mBlackTexture2D, mBlackTextureCubeMap;
|
||||
bool mBlackTexturesAreInitialized;
|
||||
|
|
|
@ -211,7 +211,7 @@ WebGLContext::BindTexture(GLenum target, WebGLTexture *tex)
|
|||
return ErrorInvalidEnumInfo("bindTexture: target", target);
|
||||
}
|
||||
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::Unknown;
|
||||
MakeContextCurrent();
|
||||
|
||||
if (tex)
|
||||
|
@ -932,36 +932,36 @@ WebGLContext::UndoFakeVertexAttrib0()
|
|||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::NeedFakeBlack()
|
||||
WebGLContextFakeBlackStatus
|
||||
WebGLContext::ResolvedFakeBlackStatus()
|
||||
{
|
||||
// handle this case first, it's the generic case
|
||||
if (mFakeBlackStatus == DoNotNeedFakeBlack)
|
||||
return false;
|
||||
if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return mFakeBlackStatus;
|
||||
|
||||
if (mFakeBlackStatus == DoNeedFakeBlack)
|
||||
return true;
|
||||
if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
|
||||
return mFakeBlackStatus;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if ((mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) ||
|
||||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()))
|
||||
if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
|
||||
(mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
|
||||
{
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
return true;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
return false;
|
||||
mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::BindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (!NeedFakeBlack())
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
if (!mBlackTexturesAreInitialized) {
|
||||
|
@ -992,11 +992,18 @@ WebGLContext::BindFakeBlackTextures()
|
|||
}
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
|
||||
WebGLTextureFakeBlackStatus s;
|
||||
s = mBound2DTextures[i]
|
||||
? mBound2DTextures[i]->ResolvedFakeBlackStatus()
|
||||
: WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
if (s != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBlackTexture2D);
|
||||
}
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
|
||||
s = mBoundCubeMapTextures[i]
|
||||
? mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus()
|
||||
: WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
if (s != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBlackTextureCubeMap);
|
||||
}
|
||||
|
@ -1007,15 +1014,15 @@ void
|
|||
WebGLContext::UnbindFakeBlackTextures()
|
||||
{
|
||||
// this is the generic case: try to return early
|
||||
if (!NeedFakeBlack())
|
||||
if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
|
||||
return;
|
||||
|
||||
for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
|
||||
if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName());
|
||||
}
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
|
||||
if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
|
||||
gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
|
||||
gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
|
||||
}
|
||||
|
|
|
@ -51,11 +51,7 @@ WebGLFramebuffer::Attachment::HasAlpha() const {
|
|||
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Format();
|
||||
else if (Renderbuffer())
|
||||
format = Renderbuffer()->InternalFormat();
|
||||
return format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_RGB5_A1;
|
||||
return FormatHasAlpha(format);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -27,7 +27,7 @@ WebGLTexture::WebGLTexture(WebGLContext *context)
|
|||
, mFacesCount(0)
|
||||
, mMaxLevelWithCustomImages(0)
|
||||
, mHaveGeneratedMipmap(false)
|
||||
, mFakeBlackStatus(DoNotNeedFakeBlack)
|
||||
, mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
mContext->MakeContextCurrent();
|
||||
|
@ -97,12 +97,6 @@ WebGLTexture::DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(GLenum texImag
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::SetDontKnowIfNeedFakeBlack() {
|
||||
mFakeBlackStatus = DontKnowIfNeedFakeBlack;
|
||||
mContext->SetDontKnowIfNeedFakeBlack();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::Bind(GLenum aTarget) {
|
||||
// this function should only be called by bindTexture().
|
||||
|
@ -124,7 +118,7 @@ WebGLTexture::Bind(GLenum aTarget) {
|
|||
if (firstTimeThisTextureIsBound) {
|
||||
mFacesCount = (mTarget == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(0);
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
|
||||
// thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R is not
|
||||
// present in GLES 2, but is present in GL and it seems as if for cube maps
|
||||
|
@ -151,14 +145,14 @@ WebGLTexture::SetImageInfo(GLenum aTarget, GLint aLevel,
|
|||
if (aLevel > 0)
|
||||
SetCustomMipmap();
|
||||
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLTexture::SetGeneratedMipmap() {
|
||||
if (!mHaveGeneratedMipmap) {
|
||||
mHaveGeneratedMipmap = true;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,128 +238,139 @@ WebGLTexture::IsMipmapCubeComplete() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLTexture::NeedFakeBlack() {
|
||||
// handle this case first, it's the generic case
|
||||
if (mFakeBlackStatus == DoNotNeedFakeBlack)
|
||||
return false;
|
||||
|
||||
if (mFakeBlackStatus == DontKnowIfNeedFakeBlack) {
|
||||
// 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.
|
||||
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (ImageInfoAtFace(face, 0).mImageDataStatus != WebGLImageDataStatus::InitializedImageData) {
|
||||
// In case of undefined texture image, we don't print any message because this is a very common
|
||||
// and often legitimate case, for example when doing asynchronous texture loading.
|
||||
// An extreme case of this is the photowall google demo.
|
||||
// Exiting early here allows us to avoid making noise on valid webgl code.
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
mContext->GenerateWarning
|
||||
("%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(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%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 (!ImageInfoAt(mTarget, 0).IsPositive()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture and its width or height is equal to zero.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%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 // cube map
|
||||
{
|
||||
bool areAllLevel0ImagesPOT = true;
|
||||
for (size_t face = 0; face < mFacesCount; ++face)
|
||||
areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
|
||||
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapCubeComplete()) {
|
||||
mContext->GenerateWarning("%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->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);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!IsCubeComplete()) {
|
||||
mContext->GenerateWarning("%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->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 = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
|
||||
!Context()->IsExtensionEnabled(WebGLContext::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, "
|
||||
"which is not compatible with gl.FLOAT by default. "
|
||||
"Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
|
||||
mFakeBlackStatus = DoNeedFakeBlack;
|
||||
}
|
||||
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 = DoNeedFakeBlack;
|
||||
}
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
if (mFakeBlackStatus == DontKnowIfNeedFakeBlack)
|
||||
mFakeBlackStatus = DoNotNeedFakeBlack;
|
||||
WebGLTextureFakeBlackStatus
|
||||
WebGLTexture::ResolvedFakeBlackStatus() {
|
||||
if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
return mFakeBlackStatus == DoNeedFakeBlack;
|
||||
// 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.
|
||||
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
if (ImageInfoAtFace(face, 0).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
|
||||
// In case of undefined texture image, we don't print any message because this is a very common
|
||||
// and often legitimate case (asynchronous texture loading).
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
mContext->GenerateWarning
|
||||
("%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 = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%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 = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!ImageInfoAt(mTarget, 0).IsPositive()) {
|
||||
mContext->GenerateWarning
|
||||
("%s is a 2D texture and its width or height is equal to zero.",
|
||||
msg_rendering_as_black);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
|
||||
mContext->GenerateWarning
|
||||
("%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 = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // cube map
|
||||
{
|
||||
bool areAllLevel0ImagesPOT = true;
|
||||
for (size_t face = 0; face < mFacesCount; ++face)
|
||||
areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
|
||||
|
||||
if (DoesMinFilterRequireMipmap())
|
||||
{
|
||||
if (!IsMipmapCubeComplete()) {
|
||||
mContext->GenerateWarning("%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 = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!areAllLevel0ImagesPOT) {
|
||||
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);
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
}
|
||||
}
|
||||
else // no mipmap required
|
||||
{
|
||||
if (!IsCubeComplete()) {
|
||||
mContext->GenerateWarning("%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 = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
} else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
|
||||
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 &&
|
||||
!Context()->IsExtensionEnabled(WebGLContext::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, "
|
||||
"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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
// We have exhausted all cases of incomplete textures, where we would need opaque black.
|
||||
// We may still need transparent black in case of uninitialized image data.
|
||||
bool hasUninitializedImageData = false;
|
||||
for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
|
||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||
hasUninitializedImageData |= (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
|
||||
}
|
||||
}
|
||||
if (hasUninitializedImageData) {
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::UninitializedImageData;
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
// we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
|
||||
// that means that we do NOT need it.
|
||||
if (mFakeBlackStatus == WebGLTextureFakeBlackStatus::Unknown) {
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown);
|
||||
return mFakeBlackStatus;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
|
||||
|
|
|
@ -21,6 +21,15 @@ inline bool is_pot_assuming_nonnegative(GLsizei x)
|
|||
return x && (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
inline bool FormatHasAlpha(GLenum format)
|
||||
{
|
||||
return format == LOCAL_GL_RGBA ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_RGB5_A1;
|
||||
}
|
||||
|
||||
// NOTE: When this class is switched to new DOM bindings, update the (then-slow)
|
||||
// WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
|
||||
class WebGLTexture MOZ_FINAL
|
||||
|
@ -181,6 +190,9 @@ public:
|
|||
// there is no way to go from having image data to not having any
|
||||
MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
|
||||
imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
|
||||
if (imageInfo.mImageDataStatus != newStatus) {
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
imageInfo.mImageDataStatus = newStatus;
|
||||
}
|
||||
|
||||
|
@ -193,7 +205,7 @@ protected:
|
|||
nsTArray<ImageInfo> mImageInfos;
|
||||
|
||||
bool mHaveGeneratedMipmap;
|
||||
FakeBlackStatus mFakeBlackStatus;
|
||||
WebGLTextureFakeBlackStatus mFakeBlackStatus;
|
||||
|
||||
void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) {
|
||||
mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, aMaxLevelWithCustomImages);
|
||||
|
@ -214,8 +226,6 @@ protected:
|
|||
|
||||
public:
|
||||
|
||||
void SetDontKnowIfNeedFakeBlack();
|
||||
|
||||
void Bind(GLenum aTarget);
|
||||
|
||||
void SetImageInfo(GLenum aTarget, GLint aLevel,
|
||||
|
@ -224,19 +234,19 @@ public:
|
|||
|
||||
void SetMinFilter(GLenum aMinFilter) {
|
||||
mMinFilter = aMinFilter;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetMagFilter(GLenum aMagFilter) {
|
||||
mMagFilter = aMagFilter;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapS(GLenum aWrapS) {
|
||||
mWrapS = aWrapS;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
void SetWrapT(GLenum aWrapT) {
|
||||
mWrapT = aWrapT;
|
||||
SetDontKnowIfNeedFakeBlack();
|
||||
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
|
||||
}
|
||||
GLenum MinFilter() const { return mMinFilter; }
|
||||
|
||||
|
@ -260,7 +270,13 @@ public:
|
|||
|
||||
bool IsMipmapCubeComplete() const;
|
||||
|
||||
bool NeedFakeBlack();
|
||||
void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x) {
|
||||
mFakeBlackStatus = x;
|
||||
mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
|
||||
}
|
||||
// Returns the current fake-black-status, except if it was Unknown,
|
||||
// in which case this function resolves it first, so it never returns Unknown.
|
||||
WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -19,7 +19,45 @@ typedef bool WebGLboolean;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
|
||||
/*
|
||||
* WebGLContextFakeBlackStatus and WebGLTextureFakeBlackStatus are enums to
|
||||
* track what needs to use a dummy 1x1 black texture, which we refer to as a
|
||||
* 'fake black' texture.
|
||||
*
|
||||
* There are generally two things that can cause us to use such 'fake black'
|
||||
* textures:
|
||||
*
|
||||
* (1) OpenGL ES rules on sampling incomplete textures specify that they
|
||||
* must be sampled as RGBA(0, 0, 0, 1) (opaque black). We have to implement these rules
|
||||
* ourselves, if only because we do not always run on OpenGL ES, and also
|
||||
* because this is dangerously close to the kind of case where we don't
|
||||
* want to trust the driver with corner cases of texture memory accesses.
|
||||
*
|
||||
* (2) OpenGL has cases where a renderbuffer, or a texture image, can contain
|
||||
* uninitialized image data. See below the comment about WebGLImageDataStatus.
|
||||
* WebGL must never have access to uninitialized image data. The WebGL 1 spec,
|
||||
* section 4.1 'Resource Restrictions', specifies that in any such case, the
|
||||
* uninitialized image data must be exposed to WebGL as if it were filled
|
||||
* with zero bytes, which means it's either opaque or transparent black
|
||||
* depending on whether the image format has alpha.
|
||||
*
|
||||
* Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
|
||||
* and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
|
||||
* reason why it needs to be faked (incomplete texture vs. uninitialized image data),
|
||||
* whereas the WebGL context can only know whether _any_ faking is currently needed at all.
|
||||
*/
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, int)
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
Needed
|
||||
MOZ_END_ENUM_CLASS(WebGLContextFakeBlackStatus)
|
||||
|
||||
MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, int)
|
||||
Unknown,
|
||||
NotNeeded,
|
||||
IncompleteTexture,
|
||||
UninitializedImageData
|
||||
MOZ_END_ENUM_CLASS(WebGLTextureFakeBlackStatus)
|
||||
|
||||
struct VertexAttrib0Status {
|
||||
enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
|
||||
|
|
Загрузка…
Ссылка в новой задаче