summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle Raaijmakers <jelle@gmta.nl>2022-09-04 21:38:39 +0200
committerLinus Groh <mail@linusgroh.de>2022-09-11 22:37:07 +0100
commitdda5987684227e31e1d7b2fca749d43f734bfc47 (patch)
tree0815e577932a70dff260f46adcfc8586314d1850
parent44953a430159117fcfbbee6f3e47bfac89f5e215 (diff)
downloadserenity-dda5987684227e31e1d7b2fca749d43f734bfc47.zip
LibGL+LibGPU+LibSoftGPU: Remove concept of `layer` in favor of `depth`
Looking at how Khronos defines layers: https://www.khronos.org/opengl/wiki/Array_Texture We both have 3D textures and layers of 2D textures, which can both be encoded in our existing `Typed3DBuffer` as depth. Since we support depth already in the GPU API, remove layer everywhere. Also pass in `Texture2D::LOG2_MAX_TEXTURE_SIZE` as the maximum number of mipmap levels, so we do not allocate 999 levels on each Image instantiation.
-rw-r--r--Userland/Libraries/LibGL/Tex/Texture2D.cpp2
-rw-r--r--Userland/Libraries/LibGL/Texture.cpp4
-rw-r--r--Userland/Libraries/LibGPU/Device.h2
-rw-r--r--Userland/Libraries/LibGPU/Image.h6
-rw-r--r--Userland/Libraries/LibSoftGPU/Device.cpp11
-rw-r--r--Userland/Libraries/LibSoftGPU/Device.h2
-rw-r--r--Userland/Libraries/LibSoftGPU/Image.cpp27
-rw-r--r--Userland/Libraries/LibSoftGPU/Image.h26
-rw-r--r--Userland/Libraries/LibSoftGPU/Sampler.cpp39
9 files changed, 54 insertions, 65 deletions
diff --git a/Userland/Libraries/LibGL/Tex/Texture2D.cpp b/Userland/Libraries/LibGL/Tex/Texture2D.cpp
index c62d7c465e..1f6c2351d0 100644
--- a/Userland/Libraries/LibGL/Tex/Texture2D.cpp
+++ b/Userland/Libraries/LibGL/Tex/Texture2D.cpp
@@ -14,7 +14,7 @@ namespace GL {
void Texture2D::download_texture_data(GLuint lod, GPU::ImageDataLayout output_layout, GLvoid* pixels)
{
VERIFY(!device_image().is_null());
- device_image()->read_texels(0, lod, { 0, 0, 0 }, pixels, output_layout);
+ device_image()->read_texels(lod, { 0, 0, 0 }, pixels, output_layout);
}
void Texture2D::upload_texture_data(GLuint lod, GLenum internal_format, GPU::ImageDataLayout input_layout, GLvoid const* pixels)
diff --git a/Userland/Libraries/LibGL/Texture.cpp b/Userland/Libraries/LibGL/Texture.cpp
index b0da6554d3..c8f9ff9d77 100644
--- a/Userland/Libraries/LibGL/Texture.cpp
+++ b/Userland/Libraries/LibGL/Texture.cpp
@@ -97,7 +97,7 @@ void GLContext::gl_copy_tex_image_2d(GLenum target, GLint level, GLenum internal
auto internal_pixel_format = pixel_format_for_internal_format(internalformat);
if (level == 0) {
- texture_2d->set_device_image(m_rasterizer->create_image(internal_pixel_format, width, height, 1, 999, 1));
+ texture_2d->set_device_image(m_rasterizer->create_image(internal_pixel_format, width, height, 1, Texture2D::LOG2_MAX_TEXTURE_SIZE));
m_sampler_config_is_dirty = true;
}
@@ -550,7 +550,7 @@ void GLContext::gl_tex_image_2d(GLenum target, GLint level, GLint internal_forma
// To be spec compliant we should create the device image once the texture has become complete and is used for rendering the first time.
// All images that were attached before the device image was created need to be stored somewhere to be used to initialize the device image once complete.
auto internal_pixel_format = pixel_format_for_internal_format(internal_format);
- texture_2d->set_device_image(m_rasterizer->create_image(internal_pixel_format, width, height, 1, 999, 1));
+ texture_2d->set_device_image(m_rasterizer->create_image(internal_pixel_format, width, height, 1, Texture2D::LOG2_MAX_TEXTURE_SIZE));
m_sampler_config_is_dirty = true;
}
diff --git a/Userland/Libraries/LibGPU/Device.h b/Userland/Libraries/LibGPU/Device.h
index 3c019b68e5..279a1355ce 100644
--- a/Userland/Libraries/LibGPU/Device.h
+++ b/Userland/Libraries/LibGPU/Device.h
@@ -55,7 +55,7 @@ public:
virtual RasterizerOptions options() const = 0;
virtual LightModelParameters light_model() const = 0;
- virtual NonnullRefPtr<Image> create_image(PixelFormat const&, u32 width, u32 height, u32 depth, u32 levels, u32 layers) = 0;
+ virtual NonnullRefPtr<Image> create_image(PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels) = 0;
virtual void set_sampler_config(unsigned, SamplerConfig const&) = 0;
virtual void set_light_state(unsigned, Light const&) = 0;
diff --git a/Userland/Libraries/LibGPU/Image.h b/Userland/Libraries/LibGPU/Image.h
index 6c882f59b0..5c9147cf41 100644
--- a/Userland/Libraries/LibGPU/Image.h
+++ b/Userland/Libraries/LibGPU/Image.h
@@ -21,9 +21,9 @@ public:
virtual ~Image() { }
- virtual void write_texels(u32 layer, u32 level, Vector3<i32> const& output_offset, void const* input_data, ImageDataLayout const&) = 0;
- virtual void read_texels(u32 layer, u32 level, Vector3<i32> const& input_offset, void* output_data, ImageDataLayout const&) const = 0;
- virtual void copy_texels(Image const& source, u32 source_layer, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_layer, u32 destination_level, Vector3<u32> const& destination_offset) = 0;
+ virtual void write_texels(u32 level, Vector3<i32> const& output_offset, void const* input_data, ImageDataLayout const&) = 0;
+ virtual void read_texels(u32 level, Vector3<i32> const& input_offset, void* output_data, ImageDataLayout const&) const = 0;
+ virtual void copy_texels(Image const& source, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_level, Vector3<u32> const& destination_offset) = 0;
void const* ownership_token() const { return m_ownership_token; }
bool has_same_ownership_token(Image const& other) const { return other.ownership_token() == ownership_token(); }
diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp
index 0033ba6d87..d0a44f9bad 100644
--- a/Userland/Libraries/LibSoftGPU/Device.cpp
+++ b/Userland/Libraries/LibSoftGPU/Device.cpp
@@ -1473,7 +1473,7 @@ void Device::blit_from_color_buffer(NonnullRefPtr<GPU::Image> image, u32 level,
auto const& softgpu_image = reinterpret_cast<Image*>(image.ptr());
auto output_layout = softgpu_image->image_data_layout(level, output_offset);
- auto* output_data = softgpu_image->texel_pointer(0, level, 0, 0, 0);
+ auto* output_data = softgpu_image->texel_pointer(level, 0, 0, 0);
PixelConverter converter { input_layout, output_layout };
auto conversion_result = converter.convert(input_data, output_data, {});
@@ -1512,7 +1512,7 @@ void Device::blit_from_depth_buffer(NonnullRefPtr<GPU::Image> image, u32 level,
auto const& softgpu_image = reinterpret_cast<Image*>(image.ptr());
auto output_layout = softgpu_image->image_data_layout(level, output_offset);
- auto* output_data = softgpu_image->texel_pointer(0, level, 0, 0, 0);
+ auto* output_data = softgpu_image->texel_pointer(level, 0, 0, 0);
PixelConverter converter { input_layout, output_layout };
auto conversion_result = converter.convert(input_data, output_data, {});
@@ -1629,15 +1629,14 @@ void Device::set_light_model_params(GPU::LightModelParameters const& lighting_mo
m_lighting_model = lighting_model;
}
-NonnullRefPtr<GPU::Image> Device::create_image(GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 levels, u32 layers)
+NonnullRefPtr<GPU::Image> Device::create_image(GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
{
VERIFY(width > 0);
VERIFY(height > 0);
VERIFY(depth > 0);
- VERIFY(levels > 0);
- VERIFY(layers > 0);
+ VERIFY(max_levels > 0);
- return adopt_ref(*new Image(this, pixel_format, width, height, depth, levels, layers));
+ return adopt_ref(*new Image(this, pixel_format, width, height, depth, max_levels));
}
void Device::set_sampler_config(unsigned sampler, GPU::SamplerConfig const& config)
diff --git a/Userland/Libraries/LibSoftGPU/Device.h b/Userland/Libraries/LibSoftGPU/Device.h
index c0b839d008..4fd6fcafac 100644
--- a/Userland/Libraries/LibSoftGPU/Device.h
+++ b/Userland/Libraries/LibSoftGPU/Device.h
@@ -64,7 +64,7 @@ public:
virtual GPU::RasterizerOptions options() const override { return m_options; }
virtual GPU::LightModelParameters light_model() const override { return m_lighting_model; }
- virtual NonnullRefPtr<GPU::Image> create_image(GPU::PixelFormat const&, u32 width, u32 height, u32 depth, u32 levels, u32 layers) override;
+ virtual NonnullRefPtr<GPU::Image> create_image(GPU::PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels) override;
virtual void set_sampler_config(unsigned, GPU::SamplerConfig const&) override;
virtual void set_light_state(unsigned, GPU::Light const&) override;
diff --git a/Userland/Libraries/LibSoftGPU/Image.cpp b/Userland/Libraries/LibSoftGPU/Image.cpp
index 9332021c48..795fc93206 100644
--- a/Userland/Libraries/LibSoftGPU/Image.cpp
+++ b/Userland/Libraries/LibSoftGPU/Image.cpp
@@ -10,11 +10,10 @@
namespace SoftGPU {
-Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels, u32 layers)
+Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format, u32 width, u32 height, u32 depth, u32 max_levels)
: GPU::Image(ownership_token)
- , m_num_layers(layers)
, m_pixel_format(pixel_format)
- , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(layers * max_levels))
+ , m_mipmap_buffers(FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>>::must_create_but_fixme_should_propagate_errors(max_levels))
{
VERIFY(pixel_format == GPU::PixelFormat::Alpha
|| pixel_format == GPU::PixelFormat::Intensity
@@ -26,7 +25,6 @@ Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format,
VERIFY(height > 0);
VERIFY(depth > 0);
VERIFY(max_levels > 0);
- VERIFY(layers > 0);
m_width_is_power_of_two = is_power_of_two(width);
m_height_is_power_of_two = is_power_of_two(height);
@@ -34,8 +32,7 @@ Image::Image(void const* ownership_token, GPU::PixelFormat const& pixel_format,
u32 level;
for (level = 0; level < max_levels; ++level) {
- for (u32 layer = 0; layer < layers; ++layer)
- m_mipmap_buffers[layer * layers + level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width, height, depth));
+ m_mipmap_buffers[level] = MUST(Typed3DBuffer<FloatVector4>::try_create(width, height, depth));
if (width <= 1 && height <= 1 && depth <= 1)
break;
@@ -77,13 +74,12 @@ GPU::ImageDataLayout Image::image_data_layout(u32 level, Vector3<i32> offset) co
};
}
-void Image::write_texels(u32 layer, u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const& input_layout)
+void Image::write_texels(u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const& input_layout)
{
- VERIFY(layer < num_layers());
VERIFY(level < num_levels());
auto output_layout = image_data_layout(level, output_offset);
- auto texel_data = texel_pointer(layer, level, 0, 0, 0);
+ auto texel_data = texel_pointer(level, 0, 0, 0);
PixelConverter converter { input_layout, output_layout };
ErrorOr<void> conversion_result;
@@ -100,31 +96,28 @@ void Image::write_texels(u32 layer, u32 level, Vector3<i32> const& output_offset
dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
}
-void Image::read_texels(u32 layer, u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const& output_layout) const
+void Image::read_texels(u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const& output_layout) const
{
- VERIFY(layer < num_layers());
VERIFY(level < num_levels());
auto input_layout = image_data_layout(level, input_offset);
PixelConverter converter { input_layout, output_layout };
- auto conversion_result = converter.convert(texel_pointer(layer, level, 0, 0, 0), output_data, {});
+ auto conversion_result = converter.convert(texel_pointer(level, 0, 0, 0), output_data, {});
if (conversion_result.is_error())
dbgln("Pixel conversion failed: {}", conversion_result.error().string_literal());
}
-void Image::copy_texels(GPU::Image const& source, u32 source_layer, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_layer, u32 destination_level, Vector3<u32> const& destination_offset)
+void Image::copy_texels(GPU::Image const& source, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_level, Vector3<u32> const& destination_offset)
{
VERIFY(source.has_same_ownership_token(*this));
auto const& src_image = static_cast<Image const&>(source);
- VERIFY(source_layer < src_image.num_layers());
VERIFY(source_level < src_image.num_levels());
VERIFY(source_offset.x() + size.x() <= src_image.level_width(source_level));
VERIFY(source_offset.y() + size.y() <= src_image.level_height(source_level));
VERIFY(source_offset.z() + size.z() <= src_image.level_depth(source_level));
- VERIFY(destination_layer < num_layers());
VERIFY(destination_level < num_levels());
VERIFY(destination_offset.x() + size.x() <= level_width(destination_level));
VERIFY(destination_offset.y() + size.y() <= level_height(destination_level));
@@ -133,8 +126,8 @@ void Image::copy_texels(GPU::Image const& source, u32 source_layer, u32 source_l
for (u32 z = 0; z < size.z(); ++z) {
for (u32 y = 0; y < size.y(); ++y) {
for (u32 x = 0; x < size.x(); ++x) {
- auto color = src_image.texel(source_layer, source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z);
- set_texel(destination_layer, destination_level, destination_offset.x() + x, destination_offset.y() + y, destination_offset.z() + z, color);
+ auto color = src_image.texel(source_level, source_offset.x() + x, source_offset.y() + y, source_offset.z() + z);
+ set_texel(destination_level, destination_offset.x() + x, destination_offset.y() + y, destination_offset.z() + z, color);
}
}
}
diff --git a/Userland/Libraries/LibSoftGPU/Image.h b/Userland/Libraries/LibSoftGPU/Image.h
index 6f92cc3ce5..23c7941155 100644
--- a/Userland/Libraries/LibSoftGPU/Image.h
+++ b/Userland/Libraries/LibSoftGPU/Image.h
@@ -20,46 +20,44 @@ namespace SoftGPU {
class Image final : public GPU::Image {
public:
- Image(void const* ownership_token, GPU::PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels, u32 layers);
+ Image(void const* ownership_token, GPU::PixelFormat const&, u32 width, u32 height, u32 depth, u32 max_levels);
u32 level_width(u32 level) const { return m_mipmap_buffers[level]->width(); }
u32 level_height(u32 level) const { return m_mipmap_buffers[level]->height(); }
u32 level_depth(u32 level) const { return m_mipmap_buffers[level]->depth(); }
u32 num_levels() const { return m_num_levels; }
- u32 num_layers() const { return m_num_layers; }
bool width_is_power_of_two() const { return m_width_is_power_of_two; }
bool height_is_power_of_two() const { return m_height_is_power_of_two; }
bool depth_is_power_of_two() const { return m_depth_is_power_of_two; }
GPU::ImageDataLayout image_data_layout(u32 level, Vector3<i32> offset) const;
- FloatVector4 texel(u32 layer, u32 level, int x, int y, int z) const
+ FloatVector4 texel(u32 level, int x, int y, int z) const
{
- return *texel_pointer(layer, level, x, y, z);
+ return *texel_pointer(level, x, y, z);
}
- void set_texel(u32 layer, u32 level, int x, int y, int z, FloatVector4 const& color)
+ void set_texel(u32 level, int x, int y, int z, FloatVector4 const& color)
{
- *texel_pointer(layer, level, x, y, z) = color;
+ *texel_pointer(level, x, y, z) = color;
}
- virtual void write_texels(u32 layer, u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const&) override;
- virtual void read_texels(u32 layer, u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const&) const override;
- virtual void copy_texels(GPU::Image const& source, u32 source_layer, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_layer, u32 destination_level, Vector3<u32> const& destination_offset) override;
+ virtual void write_texels(u32 level, Vector3<i32> const& output_offset, void const* input_data, GPU::ImageDataLayout const&) override;
+ virtual void read_texels(u32 level, Vector3<i32> const& input_offset, void* output_data, GPU::ImageDataLayout const&) const override;
+ virtual void copy_texels(GPU::Image const& source, u32 source_level, Vector3<u32> const& source_offset, Vector3<u32> const& size, u32 destination_level, Vector3<u32> const& destination_offset) override;
- FloatVector4 const* texel_pointer(u32 layer, u32 level, int x, int y, int z) const
+ FloatVector4 const* texel_pointer(u32 level, int x, int y, int z) const
{
- return m_mipmap_buffers[layer * m_num_layers + level]->buffer_pointer(x, y, z);
+ return m_mipmap_buffers[level]->buffer_pointer(x, y, z);
}
- FloatVector4* texel_pointer(u32 layer, u32 level, int x, int y, int z)
+ FloatVector4* texel_pointer(u32 level, int x, int y, int z)
{
- return m_mipmap_buffers[layer * m_num_layers + level]->buffer_pointer(x, y, z);
+ return m_mipmap_buffers[level]->buffer_pointer(x, y, z);
}
private:
u32 m_num_levels { 0 };
- u32 m_num_layers { 0 };
GPU::PixelFormat m_pixel_format;
FixedArray<RefPtr<Typed3DBuffer<FloatVector4>>> m_mipmap_buffers;
diff --git a/Userland/Libraries/LibSoftGPU/Sampler.cpp b/Userland/Libraries/LibSoftGPU/Sampler.cpp
index 42c6287d0a..b027e99af4 100644
--- a/Userland/Libraries/LibSoftGPU/Sampler.cpp
+++ b/Userland/Libraries/LibSoftGPU/Sampler.cpp
@@ -71,12 +71,12 @@ static f32x4 wrap(f32x4 value, GPU::TextureWrapMode mode, f32x4 num_texels)
}
}
-ALWAYS_INLINE static Vector4<f32x4> texel4(Image const& image, u32x4 layer, u32x4 level, u32x4 x, u32x4 y, u32x4 z)
+ALWAYS_INLINE static Vector4<f32x4> texel4(Image const& image, u32x4 level, u32x4 x, u32x4 y, u32x4 z)
{
- auto t0 = image.texel(layer[0], level[0], x[0], y[0], z[0]);
- auto t1 = image.texel(layer[1], level[1], x[1], y[1], z[1]);
- auto t2 = image.texel(layer[2], level[2], x[2], y[2], z[2]);
- auto t3 = image.texel(layer[3], level[3], x[3], y[3], z[3]);
+ auto t0 = image.texel(level[0], x[0], y[0], z[0]);
+ auto t1 = image.texel(level[1], x[1], y[1], z[1]);
+ auto t2 = image.texel(level[2], x[2], y[2], z[2]);
+ auto t3 = image.texel(level[3], x[3], y[3], z[3]);
return Vector4<f32x4> {
f32x4 { t0.x(), t1.x(), t2.x(), t3.x() },
@@ -86,14 +86,14 @@ ALWAYS_INLINE static Vector4<f32x4> texel4(Image const& image, u32x4 layer, u32x
};
}
-ALWAYS_INLINE static Vector4<f32x4> texel4border(Image const& image, u32x4 layer, u32x4 level, u32x4 x, u32x4 y, u32x4 z, FloatVector4 const& border, u32x4 w, u32x4 h)
+ALWAYS_INLINE static Vector4<f32x4> texel4border(Image const& image, u32x4 level, u32x4 x, u32x4 y, u32x4 z, FloatVector4 const& border, u32x4 w, u32x4 h)
{
auto border_mask = maskbits(x < 0 || x >= w || y < 0 || y >= h);
- auto t0 = border_mask & 1 ? border : image.texel(layer[0], level[0], x[0], y[0], z[0]);
- auto t1 = border_mask & 2 ? border : image.texel(layer[1], level[1], x[1], y[1], z[1]);
- auto t2 = border_mask & 4 ? border : image.texel(layer[2], level[2], x[2], y[2], z[2]);
- auto t3 = border_mask & 8 ? border : image.texel(layer[3], level[3], x[3], y[3], z[3]);
+ auto t0 = border_mask & 1 ? border : image.texel(level[0], x[0], y[0], z[0]);
+ auto t1 = border_mask & 2 ? border : image.texel(level[1], x[1], y[1], z[1]);
+ auto t2 = border_mask & 4 ? border : image.texel(level[2], x[2], y[2], z[2]);
+ auto t3 = border_mask & 8 ? border : image.texel(level[3], x[3], y[3], z[3]);
return Vector4<f32x4> {
f32x4 { t0.x(), t1.x(), t2.x(), t3.x() },
@@ -155,7 +155,6 @@ Vector4<AK::SIMD::f32x4> Sampler::sample_2d(Vector2<AK::SIMD::f32x4> const& uv)
Vector4<AK::SIMD::f32x4> Sampler::sample_2d_lod(Vector2<AK::SIMD::f32x4> const& uv, AK::SIMD::u32x4 level, GPU::TextureFilter filter) const
{
auto const& image = *static_ptr_cast<Image>(m_config.bound_image);
- u32x4 const layer = expand4(0u);
u32x4 const width = {
image.level_width(level[0]),
@@ -187,7 +186,7 @@ Vector4<AK::SIMD::f32x4> Sampler::sample_2d_lod(Vector2<AK::SIMD::f32x4> const&
i = image.width_is_power_of_two() ? i & width_mask : i % width;
j = image.height_is_power_of_two() ? j & height_mask : j % height;
- return texel4(image, layer, level, i, j, k);
+ return texel4(image, level, i, j, k);
}
u -= 0.5f;
@@ -223,15 +222,15 @@ Vector4<AK::SIMD::f32x4> Sampler::sample_2d_lod(Vector2<AK::SIMD::f32x4> const&
Vector4<f32x4> t0, t1, t2, t3;
if (m_config.texture_wrap_u == GPU::TextureWrapMode::Repeat && m_config.texture_wrap_v == GPU::TextureWrapMode::Repeat) {
- t0 = texel4(image, layer, level, i0, j0, k);
- t1 = texel4(image, layer, level, i1, j0, k);
- t2 = texel4(image, layer, level, i0, j1, k);
- t3 = texel4(image, layer, level, i1, j1, k);
+ t0 = texel4(image, level, i0, j0, k);
+ t1 = texel4(image, level, i1, j0, k);
+ t2 = texel4(image, level, i0, j1, k);
+ t3 = texel4(image, level, i1, j1, k);
} else {
- t1 = texel4border(image, layer, level, i1, j0, k, m_config.border_color, width, height);
- t0 = texel4border(image, layer, level, i0, j0, k, m_config.border_color, width, height);
- t2 = texel4border(image, layer, level, i0, j1, k, m_config.border_color, width, height);
- t3 = texel4border(image, layer, level, i1, j1, k, m_config.border_color, width, height);
+ t1 = texel4border(image, level, i1, j0, k, m_config.border_color, width, height);
+ t0 = texel4border(image, level, i0, j0, k, m_config.border_color, width, height);
+ t2 = texel4border(image, level, i0, j1, k, m_config.border_color, width, height);
+ t3 = texel4border(image, level, i1, j1, k, m_config.border_color, width, height);
}
f32x4 const alpha = frac_int_range(u);