예제 #1
0
// 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);
}
예제 #2
0
// 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);
}