Bug 1230089 - If sampler is bound, use parameter of sampler. r=jgilbert

--HG--
extra : commitid : JF12eiQS7m8
This commit is contained in:
Morris Tseng 2016-01-21 14:49:41 +08:00
Родитель 8fbc15e43a
Коммит 6e90a4c6fc
8 изменённых файлов: 156 добавлений и 19 удалений

Просмотреть файл

@ -47,6 +47,8 @@ WebGL2Context::DeleteSampler(WebGLSampler* sampler)
for (int n = 0; n < mGLMaxTextureUnits; n++) {
if (mBoundSamplers[n] == sampler) {
mBoundSamplers[n] = nullptr;
InvalidateResolveCacheForTextureWithTexUnit(n);
}
}
@ -88,6 +90,7 @@ WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
return ErrorInvalidOperation("bindSampler: binding deleted sampler");
WebGLContextUnchecked::BindSampler(unit, sampler);
InvalidateResolveCacheForTextureWithTexUnit(unit);
mBoundSamplers[unit] = sampler;
}
@ -104,6 +107,7 @@ WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint para
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri"))
return;
sampler->SamplerParameter1i(pname, param);
WebGLContextUnchecked::SamplerParameteri(sampler, pname, param);
}
@ -124,6 +128,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv"))
return;
sampler->SamplerParameter1i(pname, param.Data()[0]);
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data());
}
@ -143,6 +148,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv"))
return;
sampler->SamplerParameter1i(pname, param[0]);
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements());
}
@ -158,6 +164,7 @@ WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat pa
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf"))
return;
sampler->SamplerParameter1f(pname, param);
WebGLContextUnchecked::SamplerParameterf(sampler, pname, param);
}
@ -178,6 +185,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv"))
return;
sampler->SamplerParameter1f(pname, param.Data()[0]);
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data());
}
@ -197,6 +205,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv"))
return;
sampler->SamplerParameter1f(pname, param[0]);
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements());
}

Просмотреть файл

@ -332,6 +332,8 @@ public:
return ActiveBoundTextureForTarget(texTarget);
}
void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
already_AddRefed<Layer>
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager) override;

Просмотреть файл

@ -187,6 +187,19 @@ WebGLContext::IsTexParamValid(GLenum pname) const
}
}
void
WebGLContext::InvalidateResolveCacheForTextureWithTexUnit(const GLuint texUnit)
{
if (mBound2DTextures[texUnit])
mBound2DTextures[texUnit]->InvalidateResolveCache();
if (mBoundCubeMapTextures[texUnit])
mBoundCubeMapTextures[texUnit]->InvalidateResolveCache();
if (mBound3DTextures[texUnit])
mBound3DTextures[texUnit]->InvalidateResolveCache();
if (mBound2DArrayTextures[texUnit])
mBound2DArrayTextures[texUnit]->InvalidateResolveCache();
}
//////////////////////////////////////////////////////////////////////////////////////////
// GL calls

Просмотреть файл

@ -14,6 +14,15 @@ namespace mozilla {
WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
: WebGLContextBoundObject(webgl)
, mGLName(sampler)
, mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
, mMagFilter(LOCAL_GL_LINEAR)
, mWrapS(LOCAL_GL_REPEAT)
, mWrapT(LOCAL_GL_REPEAT)
, mWrapR(LOCAL_GL_REPEAT)
, mMinLod(-1000)
, mMaxLod(1000)
, mCompareMode(LOCAL_GL_NONE)
, mCompareFunc(LOCAL_GL_LEQUAL)
{
mContext->mSamplers.insertBack(this);
}
@ -44,6 +53,72 @@ WebGLSampler::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
return dom::WebGLSamplerBinding::Wrap(cx, this, givenProto);
}
void
WebGLSampler::SamplerParameter1i(GLenum pname, GLint param)
{
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_FILTER:
mMinFilter = param;
break;
case LOCAL_GL_TEXTURE_MAG_FILTER:
mMagFilter = param;
break;
case LOCAL_GL_TEXTURE_WRAP_S:
mWrapS = param;
break;
case LOCAL_GL_TEXTURE_WRAP_T:
mWrapT = param;
break;
case LOCAL_GL_TEXTURE_WRAP_R:
mWrapR = param;
break;
case LOCAL_GL_TEXTURE_COMPARE_MODE:
mCompareMode = param;
break;
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
mCompareFunc = param;
break;
default:
MOZ_CRASH("Unhandled pname");
break;
}
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
if (this == mContext->mBoundSamplers[i])
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
}
}
void
WebGLSampler::SamplerParameter1f(GLenum pname, GLfloat param)
{
switch (pname) {
case LOCAL_GL_TEXTURE_MIN_LOD:
mMinLod = param;
break;
case LOCAL_GL_TEXTURE_MAX_LOD:
mMaxLod = param;
break;
default:
MOZ_CRASH("Unhandled pname");
break;
}
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
if (this == mContext->mBoundSamplers[i])
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
}
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)

Просмотреть файл

@ -19,6 +19,7 @@ class WebGLSampler final
, public WebGLContextBoundObject
{
friend class WebGLContext2;
friend class WebGLTexture;
public:
explicit WebGLSampler(WebGLContext* webgl, GLuint sampler);
@ -30,11 +31,24 @@ public:
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
void SamplerParameter1i(GLenum pname, GLint param);
void SamplerParameter1f(GLenum pname, GLfloat param);
private:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
TexMinFilter mMinFilter;
TexMagFilter mMagFilter;
TexWrap mWrapS;
TexWrap mWrapT;
TexWrap mWrapR;
GLint mMinLod;
GLint mMaxLod;
TexCompareMode mCompareMode;
TexCompareFunc mCompareFunc;
private:
~WebGLSampler();
};

Просмотреть файл

@ -269,6 +269,22 @@ STRONG_GLENUM_BEGIN(TexWrap)
STRONG_GLENUM_VALUE(MIRRORED_REPEAT),
STRONG_GLENUM_END(TexWrap)
STRONG_GLENUM_BEGIN(TexCompareMode)
STRONG_GLENUM_VALUE(NONE),
STRONG_GLENUM_VALUE(COMPARE_REF_TO_TEXTURE),
STRONG_GLENUM_END(TexCompareMode)
STRONG_GLENUM_BEGIN(TexCompareFunc)
STRONG_GLENUM_VALUE(LEQUAL),
STRONG_GLENUM_VALUE(GEQUAL),
STRONG_GLENUM_VALUE(LESS),
STRONG_GLENUM_VALUE(GREATER),
STRONG_GLENUM_VALUE(EQUAL),
STRONG_GLENUM_VALUE(NOTEQUAL),
STRONG_GLENUM_VALUE(ALWAYS),
STRONG_GLENUM_VALUE(NEVER),
STRONG_GLENUM_END(TexCompareFunc)
STRONG_GLENUM_BEGIN(TexFormat)
STRONG_GLENUM_VALUE(NONE), // 0x0000
STRONG_GLENUM_VALUE(DEPTH_COMPONENT), // 0x1902

Просмотреть файл

@ -190,12 +190,12 @@ WebGLTexture::SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo)
}
bool
WebGLTexture::IsMipmapComplete() const
WebGLTexture::IsMipmapComplete(uint32_t texUnit) const
{
MOZ_ASSERT(DoesMinFilterRequireMipmap());
// GLES 3.0.4, p161
const uint32_t maxLevel = MaxEffectiveMipmapLevel();
const uint32_t maxLevel = MaxEffectiveMipmapLevel(texUnit);
// "* `level_base <= level_max`"
if (mBaseMipmapLevel > maxLevel)
@ -290,7 +290,7 @@ WebGLTexture::IsCubeComplete() const
}
bool
WebGLTexture::IsComplete(const char** const out_reason) const
WebGLTexture::IsComplete(uint32_t texUnit, const char** const out_reason) const
{
// Texture completeness is established at GLES 3.0.4, p160-161.
// "[A] texture is complete unless any of the following conditions hold true:"
@ -315,19 +315,23 @@ WebGLTexture::IsComplete(const char** const out_reason) const
return false;
}
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
TexMagFilter magFilter = sampler ? sampler->mMagFilter : mMagFilter;
// "* The minification filter requires a mipmap (is neither NEAREST nor LINEAR) and
// the texture is not mipmap complete."
const bool requiresMipmap = (mMinFilter != LOCAL_GL_NEAREST &&
mMinFilter != LOCAL_GL_LINEAR);
if (requiresMipmap && !IsMipmapComplete()) {
const bool requiresMipmap = (minFilter != LOCAL_GL_NEAREST &&
minFilter != LOCAL_GL_LINEAR);
if (requiresMipmap && !IsMipmapComplete(texUnit)) {
*out_reason = "Because the minification filter requires mipmapping, the texture"
" must be \"mipmap complete\".";
return false;
}
const bool isMinFilteringNearest = (mMinFilter == LOCAL_GL_NEAREST ||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
const bool isMagFilteringNearest = (mMagFilter == LOCAL_GL_NEAREST);
const bool isMinFilteringNearest = (minFilter == LOCAL_GL_NEAREST ||
minFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
const bool isMagFilteringNearest = (magFilter == LOCAL_GL_NEAREST);
const bool isFilteringNearestOnly = (isMinFilteringNearest && isMagFilteringNearest);
if (!isFilteringNearestOnly) {
auto formatUsage = baseImageInfo.mFormat;
@ -394,9 +398,11 @@ WebGLTexture::IsComplete(const char** const out_reason) const
// non-power-of-two images, and either the texture wrap mode is not
// CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR."
if (!baseImageInfo.IsPowerOfTwo()) {
TexWrap wrapS = sampler ? sampler->mWrapS : mWrapS;
TexWrap wrapT = sampler ? sampler->mWrapT : mWrapT;
// "either the texture wrap mode is not CLAMP_TO_EDGE"
if (mWrapS != LOCAL_GL_CLAMP_TO_EDGE ||
mWrapT != LOCAL_GL_CLAMP_TO_EDGE)
if (wrapS != LOCAL_GL_CLAMP_TO_EDGE ||
wrapT != LOCAL_GL_CLAMP_TO_EDGE)
{
*out_reason = "Non-power-of-two textures must have a wrap mode of"
" CLAMP_TO_EDGE.";
@ -421,10 +427,12 @@ WebGLTexture::IsComplete(const char** const out_reason) const
uint32_t
WebGLTexture::MaxEffectiveMipmapLevel() const
WebGLTexture::MaxEffectiveMipmapLevel(uint32_t texUnit) const
{
if (mMinFilter == LOCAL_GL_NEAREST ||
mMinFilter == LOCAL_GL_LINEAR)
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
if (minFilter == LOCAL_GL_NEAREST ||
minFilter == LOCAL_GL_LINEAR)
{
// No mips used.
return mBaseMipmapLevel;
@ -442,7 +450,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
FakeBlackType* const out_fakeBlack)
{
const char* incompleteReason;
if (!IsComplete(&incompleteReason)) {
if (!IsComplete(texUnit, &incompleteReason)) {
if (incompleteReason) {
mContext->GenerateWarning("%s: Active texture %u for target 0x%04x is"
" 'incomplete', and will be rendered as"
@ -458,7 +466,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
bool hasUninitializedData = false;
bool hasInitializedData = false;
const auto maxLevel = MaxEffectiveMipmapLevel();
const auto maxLevel = MaxEffectiveMipmapLevel(texUnit);
MOZ_ASSERT(mBaseMipmapLevel <= maxLevel);
for (uint32_t level = mBaseMipmapLevel; level <= maxLevel; level++) {
for (uint8_t face = 0; face < mFaceCount; face++) {

Просмотреть файл

@ -284,7 +284,7 @@ protected:
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
uint32_t MaxEffectiveMipmapLevel() const;
uint32_t MaxEffectiveMipmapLevel(uint32_t texUnit) const;
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
GLenum rawTexImageTarget = texImageTarget.get();
@ -369,11 +369,11 @@ public:
bool AreAllLevel0ImageInfosEqual() const;
bool IsMipmapComplete() const;
bool IsMipmapComplete(uint32_t texUnit) const;
bool IsCubeComplete() const;
bool IsComplete(const char** const out_reason) const;
bool IsComplete(uint32_t texUnit, const char** const out_reason) const;
bool IsMipmapCubeComplete() const;