// Here we have to support all pnames with both int and float params. // See this discussion: // https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html void WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, GLint* maybeIntParam, GLfloat* maybeFloatParam) { MOZ_ASSERT(maybeIntParam || maybeFloatParam); GLint intParam = maybeIntParam ? *maybeIntParam : GLint(*maybeFloatParam); GLfloat floatParam = maybeFloatParam ? *maybeFloatParam : GLfloat(*maybeIntParam); bool isPNameValid = false; switch (pname) { // GLES 2.0.25 p76: case LOCAL_GL_TEXTURE_WRAP_S: case LOCAL_GL_TEXTURE_WRAP_T: case LOCAL_GL_TEXTURE_MIN_FILTER: case LOCAL_GL_TEXTURE_MAG_FILTER: isPNameValid = true; break; // GLES 3.0.4 p149-150: case LOCAL_GL_TEXTURE_BASE_LEVEL: case LOCAL_GL_TEXTURE_COMPARE_MODE: case LOCAL_GL_TEXTURE_COMPARE_FUNC: case LOCAL_GL_TEXTURE_MAX_LEVEL: case LOCAL_GL_TEXTURE_MAX_LOD: case LOCAL_GL_TEXTURE_MIN_LOD: case LOCAL_GL_TEXTURE_WRAP_R: if (mContext->IsWebGL2()) isPNameValid = true; break; case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: if (mContext->IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) isPNameValid = true; break; } if (!isPNameValid) { mContext->ErrorInvalidEnumInfo("texParameter: pname", pname); return; } //////////////// // Validate params and invalidate if needed. bool paramBadEnum = false; bool paramBadValue = false; switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: case LOCAL_GL_TEXTURE_MAX_LEVEL: paramBadValue = (intParam < 0); break; case LOCAL_GL_TEXTURE_COMPARE_MODE: paramBadValue = (intParam != LOCAL_GL_NONE && intParam != LOCAL_GL_COMPARE_REF_TO_TEXTURE); break; case LOCAL_GL_TEXTURE_COMPARE_FUNC: switch (intParam) { case LOCAL_GL_LEQUAL: case LOCAL_GL_GEQUAL: case LOCAL_GL_LESS: case LOCAL_GL_GREATER: case LOCAL_GL_EQUAL: case LOCAL_GL_NOTEQUAL: case LOCAL_GL_ALWAYS: case LOCAL_GL_NEVER: break; default: paramBadValue = true; break; } break; case LOCAL_GL_TEXTURE_MIN_FILTER: switch (intParam) { case LOCAL_GL_NEAREST: case LOCAL_GL_LINEAR: case LOCAL_GL_NEAREST_MIPMAP_NEAREST: case LOCAL_GL_LINEAR_MIPMAP_NEAREST: case LOCAL_GL_NEAREST_MIPMAP_LINEAR: case LOCAL_GL_LINEAR_MIPMAP_LINEAR: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_MAG_FILTER: switch (intParam) { case LOCAL_GL_NEAREST: case LOCAL_GL_LINEAR: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_WRAP_S: case LOCAL_GL_TEXTURE_WRAP_T: case LOCAL_GL_TEXTURE_WRAP_R: switch (intParam) { case LOCAL_GL_CLAMP_TO_EDGE: case LOCAL_GL_MIRRORED_REPEAT: case LOCAL_GL_REPEAT: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: if (maybeFloatParam && floatParam < 1.0f) paramBadValue = true; else if (maybeIntParam && intParam < 1) paramBadValue = true; break; } if (paramBadEnum) { if (maybeIntParam) { mContext->ErrorInvalidEnum("texParameteri: pname 0x%04x: Invalid param" " 0x%04x.", pname, intParam); } else { mContext->ErrorInvalidEnum("texParameterf: pname 0x%04x: Invalid param %g.", pname, floatParam); } return; } if (paramBadValue) { if (maybeIntParam) { mContext->ErrorInvalidValue("texParameteri: pname 0x%04x: Invalid param %i" " (0x%x).", pname, intParam, intParam); } else { mContext->ErrorInvalidValue("texParameterf: pname 0x%04x: Invalid param %g.", pname, floatParam); } return; } //////////////// // Store any needed values switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: mBaseMipmapLevel = intParam; ClampLevelBaseAndMax(); break; case LOCAL_GL_TEXTURE_MAX_LEVEL: mMaxMipmapLevel = intParam; ClampLevelBaseAndMax(); break; case LOCAL_GL_TEXTURE_MIN_FILTER: mMinFilter = intParam; break; case LOCAL_GL_TEXTURE_MAG_FILTER: mMagFilter = intParam; break; case LOCAL_GL_TEXTURE_WRAP_S: mWrapS = intParam; break; case LOCAL_GL_TEXTURE_WRAP_T: mWrapT = intParam; break; // We don't actually need to store the WRAP_R, since it doesn't change texture // completeness rules. } // Only a couple of pnames don't need to invalidate our resolve status cache. switch (pname) { case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: case LOCAL_GL_TEXTURE_WRAP_R: break; default: InvalidateResolveCache(); break; } //////////////// mContext->MakeContextCurrent(); if (maybeIntParam) mContext->gl->fTexParameteri(texTarget.get(), pname, intParam); else mContext->gl->fTexParameterf(texTarget.get(), pname, floatParam); }
// Here we have to support all pnames with both int and float params. // See this discussion: // https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html void WebGLTexture::TexParameter(TexTarget texTarget, GLenum pname, const FloatOrInt& param) { bool isPNameValid = false; switch (pname) { // GLES 2.0.25 p76: case LOCAL_GL_TEXTURE_WRAP_S: case LOCAL_GL_TEXTURE_WRAP_T: case LOCAL_GL_TEXTURE_MIN_FILTER: case LOCAL_GL_TEXTURE_MAG_FILTER: isPNameValid = true; break; // GLES 3.0.4 p149-150: case LOCAL_GL_TEXTURE_BASE_LEVEL: case LOCAL_GL_TEXTURE_COMPARE_MODE: case LOCAL_GL_TEXTURE_COMPARE_FUNC: case LOCAL_GL_TEXTURE_MAX_LEVEL: case LOCAL_GL_TEXTURE_MAX_LOD: case LOCAL_GL_TEXTURE_MIN_LOD: case LOCAL_GL_TEXTURE_WRAP_R: if (mContext->IsWebGL2()) isPNameValid = true; break; case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: if (mContext->IsExtensionEnabled( WebGLExtensionID::EXT_texture_filter_anisotropic)) isPNameValid = true; break; } if (!isPNameValid) { mContext->ErrorInvalidEnumInfo("texParameter: pname", pname); return; } //////////////// // Validate params and invalidate if needed. bool paramBadEnum = false; bool paramBadValue = false; switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: case LOCAL_GL_TEXTURE_MAX_LEVEL: paramBadValue = (param.i < 0); break; case LOCAL_GL_TEXTURE_COMPARE_MODE: paramBadValue = (param.i != LOCAL_GL_NONE && param.i != LOCAL_GL_COMPARE_REF_TO_TEXTURE); break; case LOCAL_GL_TEXTURE_COMPARE_FUNC: switch (param.i) { case LOCAL_GL_LEQUAL: case LOCAL_GL_GEQUAL: case LOCAL_GL_LESS: case LOCAL_GL_GREATER: case LOCAL_GL_EQUAL: case LOCAL_GL_NOTEQUAL: case LOCAL_GL_ALWAYS: case LOCAL_GL_NEVER: break; default: paramBadValue = true; break; } break; case LOCAL_GL_TEXTURE_MIN_FILTER: switch (param.i) { case LOCAL_GL_NEAREST: case LOCAL_GL_LINEAR: case LOCAL_GL_NEAREST_MIPMAP_NEAREST: case LOCAL_GL_LINEAR_MIPMAP_NEAREST: case LOCAL_GL_NEAREST_MIPMAP_LINEAR: case LOCAL_GL_LINEAR_MIPMAP_LINEAR: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_MAG_FILTER: switch (param.i) { case LOCAL_GL_NEAREST: case LOCAL_GL_LINEAR: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_WRAP_S: case LOCAL_GL_TEXTURE_WRAP_T: case LOCAL_GL_TEXTURE_WRAP_R: switch (param.i) { case LOCAL_GL_CLAMP_TO_EDGE: case LOCAL_GL_MIRRORED_REPEAT: case LOCAL_GL_REPEAT: break; default: paramBadEnum = true; break; } break; case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT: if (param.f < 1.0f) paramBadValue = true; break; } if (paramBadEnum) { if (!param.isFloat) { mContext->ErrorInvalidEnum( "pname 0x%04x: Invalid param" " 0x%04x.", pname, param.i); } else { mContext->ErrorInvalidEnum("pname 0x%04x: Invalid param %g.", pname, param.f); } return; } if (paramBadValue) { if (!param.isFloat) { mContext->ErrorInvalidValue( "pname 0x%04x: Invalid param %i" " (0x%x).", pname, param.i, param.i); } else { mContext->ErrorInvalidValue("pname 0x%04x: Invalid param %g.", pname, param.f); } return; } //////////////// // Store any needed values FloatOrInt clamped = param; bool invalidate = true; switch (pname) { case LOCAL_GL_TEXTURE_BASE_LEVEL: mBaseMipmapLevel = clamped.i; ClampLevelBaseAndMax(); clamped = FloatOrInt(GLint(mBaseMipmapLevel)); break; case LOCAL_GL_TEXTURE_MAX_LEVEL: mMaxMipmapLevel = clamped.i; ClampLevelBaseAndMax(); clamped = FloatOrInt(GLint(mMaxMipmapLevel)); break; case LOCAL_GL_TEXTURE_MIN_FILTER: mSamplingState.minFilter = clamped.i; break; case LOCAL_GL_TEXTURE_MAG_FILTER: mSamplingState.magFilter = clamped.i; break; case LOCAL_GL_TEXTURE_WRAP_S: mSamplingState.wrapS = clamped.i; break; case LOCAL_GL_TEXTURE_WRAP_T: mSamplingState.wrapT = clamped.i; break; case LOCAL_GL_TEXTURE_COMPARE_MODE: mSamplingState.compareMode = clamped.i; break; default: invalidate = false; // Texture completeness will not change. break; } if (invalidate) { InvalidateCaches(); } //////////////// if (!clamped.isFloat) mContext->gl->fTexParameteri(texTarget.get(), pname, clamped.i); else mContext->gl->fTexParameterf(texTarget.get(), pname, clamped.f); }