Example #1
0
void
WebGLTexture::GenerateMipmap(TexTarget texTarget)
{
    // GLES 3.0.4 p160:
    // "Mipmap generation replaces texel array levels level base + 1 through q with arrays
    //  derived from the level base array, regardless of their previous contents. All
    //  other mipmap arrays, including the level base array, are left unchanged by this
    //  computation."
    const ImageInfo& baseImageInfo = BaseImageInfo();
    if (!baseImageInfo.IsDefined()) {
        mContext->ErrorInvalidOperation("generateMipmap: The base level of the texture is"
                                        " not defined.");
        return;
    }

    if (IsCubeMap() && !IsCubeComplete()) {
      mContext->ErrorInvalidOperation("generateMipmap: Cube maps must be \"cube"
                                      " complete\".");
      return;
    }

    if (!mContext->IsWebGL2() && !baseImageInfo.IsPowerOfTwo()) {
        mContext->ErrorInvalidOperation("generateMipmap: The base level of the texture"
                                        " does not have power-of-two dimensions.");
        return;
    }

    auto format = baseImageInfo.mFormat->format;
    if (format->compression) {
        mContext->ErrorInvalidOperation("generateMipmap: Texture data at base level is"
                                        " compressed.");
        return;
    }

    if (format->hasDepth) {
        mContext->ErrorInvalidOperation("generateMipmap: Depth textures are not"
                                        " supported.");
        return;
    }

    // OpenGL ES 3.0.4 p160:
    // If the level base array was not specified with an unsized internal format from
    // table 3.3 or a sized internal format that is both color-renderable and
    // texture-filterable according to table 3.13, an INVALID_OPERATION error
    // is generated.
    const auto usage = baseImageInfo.mFormat;
    bool canGenerateMipmap = (usage->isRenderable && usage->isFilterable);
    switch (usage->format->effectiveFormat) {
    case webgl::EffectiveFormat::Luminance8:
    case webgl::EffectiveFormat::Alpha8:
    case webgl::EffectiveFormat::Luminance8Alpha8:
        // Non-color-renderable formats from Table 3.3.
        canGenerateMipmap = true;
        break;
    default:
        break;
    }

    if (!canGenerateMipmap) {
        mContext->ErrorInvalidOperation("generateMipmap: Texture at base level is not unsized"
                                        " internal format or is not"
                                        " color-renderable or texture-filterable.");
        return;
    }

    // Done with validation. Do the operation.

    mContext->MakeContextCurrent();
    gl::GLContext* gl = mContext->gl;

    if (gl->WorkAroundDriverBugs()) {
        // bug 696495 - to work around failures in the texture-mips.html test on various drivers, we
        // set the minification filter before calling glGenerateMipmap. This should not carry a significant performance
        // overhead so we do it unconditionally.
        //
        // note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See Chromium bug 101105.
        gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER,
                           LOCAL_GL_NEAREST_MIPMAP_NEAREST);
        gl->fGenerateMipmap(texTarget.get());
        gl->fTexParameteri(texTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER,
                           mMinFilter.get());
    } else {
        gl->fGenerateMipmap(texTarget.get());
    }

    // Record the results.
    // Note that we don't use MaxEffectiveMipmapLevel() here, since that returns
    // mBaseMipmapLevel if the min filter doesn't require mipmaps.
    const uint32_t lastLevel = mBaseMipmapLevel + baseImageInfo.MaxMipmapLevels() - 1;
    PopulateMipChain(mBaseMipmapLevel, lastLevel);
}
Example #2
0
void WebGLTexture::GenerateMipmap() {
  // GLES 3.0.4 p160:
  // "Mipmap generation replaces texel array levels level base + 1 through q
  //  with arrrays derived from the level base array, regardless of their
  //  previous contents. All other mipmap arrays, including the level base
  //  array, are left unchanged by this computation."
  // But only check and init the base level.
  const bool ensureInit = true;
  const bool skipMips = true;
  const auto completeness = CalcCompletenessInfo(ensureInit, skipMips);
  if (!completeness || !completeness->levels) {
    mContext->ErrorInvalidOperation(
        "The texture's base level must be complete.");
    return;
  }
  const auto& usage = completeness->usage;
  const auto& format = usage->format;
  if (!mContext->IsWebGL2()) {
    if (!completeness->powerOfTwo) {
      mContext->ErrorInvalidOperation(
          "The base level of the texture does not"
          " have power-of-two dimensions.");
      return;
    }
    if (format->isSRGB) {
      mContext->ErrorInvalidOperation(
          "EXT_sRGB forbids GenerateMipmap with"
          " sRGB.");
      return;
    }
  }

  if (format->compression) {
    mContext->ErrorInvalidOperation(
        "Texture data at base level is compressed.");
    return;
  }

  if (format->d) {
    mContext->ErrorInvalidOperation("Depth textures are not supported.");
    return;
  }

  // OpenGL ES 3.0.4 p160:
  // If the level base array was not specified with an unsized internal format
  // from table 3.3 or a sized internal format that is both color-renderable and
  // texture-filterable according to table 3.13, an INVALID_OPERATION error
  // is generated.
  bool canGenerateMipmap = (usage->IsRenderable() && usage->isFilterable);
  switch (usage->format->effectiveFormat) {
    case webgl::EffectiveFormat::Luminance8:
    case webgl::EffectiveFormat::Alpha8:
    case webgl::EffectiveFormat::Luminance8Alpha8:
      // Non-color-renderable formats from Table 3.3.
      canGenerateMipmap = true;
      break;
    default:
      break;
  }

  if (!canGenerateMipmap) {
    mContext->ErrorInvalidOperation(
        "Texture at base level is not unsized"
        " internal format or is not"
        " color-renderable or texture-filterable.");
    return;
  }

  // Done with validation. Do the operation.

  gl::GLContext* gl = mContext->gl;

  if (gl->WorkAroundDriverBugs()) {
    // bug 696495 - to work around failures in the texture-mips.html test on
    // various drivers, we set the minification filter before calling
    // glGenerateMipmap. This should not carry a significant performance
    // overhead so we do it unconditionally.
    //
    // note that the choice of GL_NEAREST_MIPMAP_NEAREST really matters. See
    // Chromium bug 101105.
    gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER,
                       LOCAL_GL_NEAREST_MIPMAP_NEAREST);
    gl->fGenerateMipmap(mTarget.get());
    gl->fTexParameteri(mTarget.get(), LOCAL_GL_TEXTURE_MIN_FILTER,
                       mSamplingState.minFilter.get());
  } else {
    gl->fGenerateMipmap(mTarget.get());
  }

  // Record the results.

  const auto maxLevel = EffectiveMaxLevel();
  PopulateMipChain(maxLevel);
}