use crate::error::{FilterChainError, Result};
use crate::framebuffer::GLImage;
use crate::gl::LoadLut;
use crate::texture::InputTexture;
use glow::{HasContext, PixelUnpackData};
use librashader_common::map::FastHashMap;
use librashader_pack::TextureResource;
use librashader_runtime::image::{ImageError, LoadedTexture, UVDirection};
use librashader_runtime::scaling::MipmapSize;
use rayon::prelude::*;
use std::num::NonZeroU32;
pub struct Gl3LutLoad;
impl LoadLut for Gl3LutLoad {
fn load_luts(
context: &glow::Context,
textures: Vec<TextureResource>,
) -> Result<FastHashMap<usize, InputTexture>> {
let mut luts = FastHashMap::default();
let pixel_unpack = unsafe { context.get_parameter_i32(glow::PIXEL_UNPACK_BUFFER_BINDING) };
let textures = textures
.into_par_iter()
.map(|texture| LoadedTexture::from_texture(texture, UVDirection::TopLeft))
.collect::<std::result::Result<Vec<LoadedTexture>, ImageError>>()?;
for (index, LoadedTexture { meta, image }) in textures.iter().enumerate() {
let levels = if meta.mipmap {
image.size.calculate_miplevels()
} else {
1u32
};
let handle = unsafe {
let handle = context
.create_texture()
.map_err(FilterChainError::GlError)?;
context.bind_texture(glow::TEXTURE_2D, Some(handle));
context.tex_storage_2d(
glow::TEXTURE_2D,
levels as i32,
glow::RGBA8,
image.size.width as i32,
image.size.height as i32,
);
context.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 0);
context.pixel_store_i32(glow::UNPACK_ALIGNMENT, 4);
context.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None);
context.tex_sub_image_2d(
glow::TEXTURE_2D,
0,
0,
0,
image.size.width as i32,
image.size.height as i32,
glow::RGBA,
glow::UNSIGNED_BYTE,
PixelUnpackData::Slice(Some(&image.bytes)),
);
let mipmap = levels > 1;
if mipmap {
context.generate_mipmap(glow::TEXTURE_2D);
}
context.bind_texture(glow::TEXTURE_2D, None);
handle
};
luts.insert(
index,
InputTexture {
image: GLImage {
handle: Some(handle),
format: glow::RGBA8,
size: image.size,
},
filter: meta.filter_mode,
mip_filter: meta.filter_mode,
wrap_mode: meta.wrap_mode,
},
);
}
unsafe {
let pixel_unpack = NonZeroU32::try_from(pixel_unpack as u32)
.ok()
.map(glow::NativeBuffer);
context.bind_buffer(glow::PIXEL_UNPACK_BUFFER, pixel_unpack);
};
Ok(luts)
}
}