Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions impeller/core/formats.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <functional>
#include <memory>
#include <string>
#include <type_traits>

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/logging.h"
Expand Down Expand Up @@ -404,19 +403,32 @@ struct Viewport {
}
};

/// @brief Describes how the texture should be sampled when the texture
/// is being shrunk (minified) or expanded (magnified) to fit to
/// the sample point.
enum class MinMagFilter {
/// Select nearest to the sample point. Most widely supported.
kNearest,

/// Select two points and linearly interpolate between them. Some formats
/// may not support this.
kLinear,
};

/// @brief Options for selecting and filtering between mipmap levels.
enum class MipFilter {
/// Sample from the nearest mip level.
/// @brief The texture is sampled as if it only had a single mipmap level.
///
/// All samples are read from level 0.
kBase,

/// @brief The nearst mipmap level is selected.
kNearest,
/// Sample from the two nearest mip levels and linearly interpolate between
/// them.

/// @brief Sample from the two nearest mip levels and linearly interpolate.
///
/// If the filter falls between levels, both levels are sampled, and
/// their results linearly interpolated between levels.
kLinear,
};

Expand Down
5 changes: 5 additions & 0 deletions impeller/core/sampler_descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ class Context;
struct SamplerDescriptor final : public Comparable<SamplerDescriptor> {
MinMagFilter min_filter = MinMagFilter::kNearest;
MinMagFilter mag_filter = MinMagFilter::kNearest;

// TODO(https://github.com/flutter/flutter/issues/148253):
// `MipFilter::kNearest` is the default value for mip filters, as it
// cooresponds with the framework's `FilterQuality.low`. If we ever change the
// default filter quality, we should update this function to match.
MipFilter mip_filter = MipFilter::kNearest;

SamplerAddressMode width_address_mode = SamplerAddressMode::kClampToEdge;
Expand Down
1 change: 1 addition & 0 deletions impeller/display_list/dl_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ static impeller::SamplerDescriptor ToSamplerDescriptor(
switch (options) {
case flutter::DlImageSampling::kNearestNeighbor:
desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest;
desc.mip_filter = impeller::MipFilter::kBase;
desc.label = "Nearest Sampler";
break;
case flutter::DlImageSampling::kLinear:
Expand Down
4 changes: 3 additions & 1 deletion impeller/entity/contents/text_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ bool TextContents::Render(const ContentContext& renderer,
sampler_desc.min_filter = MinMagFilter::kLinear;
sampler_desc.mag_filter = MinMagFilter::kLinear;
}
sampler_desc.mip_filter = MipFilter::kNearest;

// No mipmaps for glyph atlas (glyphs are generated at exact scales).
sampler_desc.mip_filter = MipFilter::kBase;

FS::BindGlyphAtlasSampler(
pass, // command
Expand Down
37 changes: 21 additions & 16 deletions impeller/renderer/backend/gles/sampler_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@ SamplerGLES::SamplerGLES(SamplerDescriptor desc) : Sampler(std::move(desc)) {}

SamplerGLES::~SamplerGLES() = default;

static GLint ToParam(MinMagFilter minmag_filter,
std::optional<MipFilter> mip_filter = std::nullopt) {
if (!mip_filter.has_value()) {
switch (minmag_filter) {
case MinMagFilter::kNearest:
return GL_NEAREST;
case MinMagFilter::kLinear:
return GL_LINEAR;
}
FML_UNREACHABLE();
static GLint ToParam(MinMagFilter minmag_filter) {
switch (minmag_filter) {
case MinMagFilter::kNearest:
return GL_NEAREST;
case MinMagFilter::kLinear:
return GL_LINEAR;
}
FML_UNREACHABLE();
}

switch (mip_filter.value()) {
static GLint ToParam(MinMagFilter minmag_filter, MipFilter mip_filter) {
switch (mip_filter) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinmaygarde to confirm, I think I remember this being weird because I had to fake support no mips.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we still need to treat an unspecified param as kBase here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PTAL again, made some adjustments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me

case MipFilter::kBase:
return ToParam(minmag_filter);
case MipFilter::kNearest:
switch (minmag_filter) {
case MinMagFilter::kNearest:
Expand Down Expand Up @@ -82,14 +83,18 @@ bool SamplerGLES::ConfigureBoundTexture(const TextureGLES& texture,
}
const auto& desc = GetDescriptor();

std::optional<MipFilter> mip_filter = std::nullopt;
GLint mag_filter = ToParam(desc.mag_filter);

// If the texture doesn't have mipmaps, we can't use mip filtering.
GLint min_filter;
if (texture.GetTextureDescriptor().mip_count > 1) {
mip_filter = desc.mip_filter;
min_filter = ToParam(desc.min_filter, desc.mip_filter);
} else {
min_filter = ToParam(desc.min_filter);
}

gl.TexParameteri(*target, GL_TEXTURE_MIN_FILTER,
ToParam(desc.min_filter, mip_filter));
gl.TexParameteri(*target, GL_TEXTURE_MAG_FILTER, ToParam(desc.mag_filter));
gl.TexParameteri(*target, GL_TEXTURE_MIN_FILTER, min_filter);
gl.TexParameteri(*target, GL_TEXTURE_MAG_FILTER, mag_filter);

const auto supports_decal_mode =
gl.GetCapabilities()->SupportsDecalSamplerAddressMode();
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/backend/metal/formats_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ constexpr MTLSamplerMinMagFilter ToMTLSamplerMinMagFilter(MinMagFilter filter) {

constexpr MTLSamplerMipFilter ToMTLSamplerMipFilter(MipFilter filter) {
switch (filter) {
case MipFilter::kBase:
return MTLSamplerMipFilterNotMipmapped;
case MipFilter::kNearest:
return MTLSamplerMipFilterNearest;
case MipFilter::kLinear:
Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/backend/vulkan/formats_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ constexpr vk::Filter ToVKSamplerMinMagFilter(MinMagFilter filter) {

constexpr vk::SamplerMipmapMode ToVKSamplerMipmapMode(MipFilter filter) {
switch (filter) {
case MipFilter::kBase:
case MipFilter::kNearest:
return vk::SamplerMipmapMode::eNearest;
case MipFilter::kLinear:
Expand Down
18 changes: 15 additions & 3 deletions impeller/renderer/backend/vulkan/sampler_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/yuv_conversion_vk.h"
#include "vulkan/vulkan_core.h"

namespace impeller {

static vk::UniqueSampler CreateSampler(
const vk::Device& device,
const SamplerDescriptor& desc,
const std::shared_ptr<YUVConversionVK>& yuv_conversion) {
const auto mip_map = ToVKSamplerMipmapMode(desc.mip_filter);

const auto min_filter = ToVKSamplerMinMagFilter(desc.min_filter);
const auto mag_filter = ToVKSamplerMinMagFilter(desc.mag_filter);

Expand All @@ -36,9 +35,22 @@ static vk::UniqueSampler CreateSampler(
sampler_info.addressModeV = address_mode_v;
sampler_info.addressModeW = address_mode_w;
sampler_info.borderColor = vk::BorderColor::eFloatTransparentBlack;
sampler_info.mipmapMode = mip_map;
sampler_info.maxLod = VK_LOD_CLAMP_NONE;

// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkSamplerCreateInfo.html#_description
switch (desc.mip_filter) {
case MipFilter::kBase:
sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
sampler_info.minLod = sampler_info.maxLod = 0.0f;
break;
case MipFilter::kNearest:
sampler_info.mipmapMode = vk::SamplerMipmapMode::eNearest;
break;
case MipFilter::kLinear:
sampler_info.mipmapMode = vk::SamplerMipmapMode::eLinear;
break;
}

if (yuv_conversion && yuv_conversion->IsValid()) {
sampler_chain.get<vk::SamplerYcbcrConversionInfo>().conversion =
yuv_conversion->GetConversion();
Expand Down
5 changes: 3 additions & 2 deletions impeller/renderer/renderer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,9 @@ TEST_P(RendererTest, CanGenerateMipmaps) {
bool first_frame = true;
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
Renderer::RenderCallback callback = [&](RenderTarget& render_target) {
const char* mip_filter_names[] = {"Nearest", "Linear"};
const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear};
const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
MipFilter::kLinear};
const char* min_filter_names[] = {"Nearest", "Linear"};
const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
MinMagFilter::kLinear};
Expand Down