use crate::core::image::HostImage; use crate::core::texture::{FloatTexture as HostFloatTexture, SpectrumTexture as HostSpectrumTexture}; use crate::spectra::default_colorspace; use crate::Arena; use shared::core::image::Image; use shared::core::texture::{FloatTexture, SpectrumTexture}; use shared::textures::*; use shared::Ptr; use std::sync::Arc; pub trait Upload { type Target; fn upload(self, arena: &Arena) -> Self::Target; } fn convert_float(tex: &HostFloatTexture, arena: &Arena) -> FloatTexture { match tex { HostFloatTexture::Constant(t) => FloatTexture::Constant(*t), HostFloatTexture::Bilerp(t) => FloatTexture::Bilerp(*t), HostFloatTexture::Checkerboard(t) => FloatTexture::Checkerboard(*t), HostFloatTexture::Dots(t) => FloatTexture::Dots(*t), HostFloatTexture::FBm(t) => FloatTexture::FBm(*t), HostFloatTexture::Windy(t) => FloatTexture::Windy(*t), HostFloatTexture::Wrinkled(t) => FloatTexture::Wrinkled(*t), HostFloatTexture::Scaled(t) => { let tex = arena.alloc(convert_float(t.tex.as_ref(), arena)); let scale = arena.alloc(convert_float(t.scale.as_ref(), arena)); FloatTexture::Scaled(FloatScaledTexture { tex, scale }) } HostFloatTexture::Mix(t) => { let tex1 = arena.alloc(convert_float(t.tex1.as_ref(), arena)); let tex2 = arena.alloc(convert_float(t.tex2.as_ref(), arena)); let amount = arena.alloc(convert_float(t.amount.as_ref(), arena)); FloatTexture::Mix(FloatMixTexture { tex1, tex2, amount }) } HostFloatTexture::DirectionMix(t) => { let tex1 = arena.alloc(convert_float(t.tex1.as_ref(), arena)); let tex2 = arena.alloc(convert_float(t.tex2.as_ref(), arena)); FloatTexture::DirectionMix(FloatDirectionMixTexture { tex1, tex2, dir: t.dir, }) } HostFloatTexture::Image(t) => { let image = arena.alloc(t.base.mipmap.base_image().inner.clone()); let tex_obj = arena.get_texture_object(&t.base.mipmap); FloatTexture::Image(FloatImageTexture { image, mapping: t.base.mapping, wrap_mode: t.base.mipmap.wrap_mode, tex_obj, scale: t.base.scale, invert: t.base.invert, }) } } } fn convert_spectrum(tex: &HostSpectrumTexture, arena: &Arena) -> SpectrumTexture { match tex { HostSpectrumTexture::Constant(t) => SpectrumTexture::Constant(*t), HostSpectrumTexture::Bilerp(t) => SpectrumTexture::Bilerp(*t), HostSpectrumTexture::Checkerboard(t) => SpectrumTexture::Checkerboard(*t), HostSpectrumTexture::Dots(t) => SpectrumTexture::Dots(*t), HostSpectrumTexture::Marble(t) => SpectrumTexture::Marble(*t), HostSpectrumTexture::Scaled(t) => { let tex = arena.alloc(convert_spectrum(t.tex.as_ref(), arena)); let scale = arena.alloc(convert_float(t.scale.as_ref(), arena)); SpectrumTexture::Scaled(SpectrumScaledTexture { tex, scale }) } HostSpectrumTexture::Mix(t) => { let tex1 = arena.alloc(convert_spectrum(t.tex1.as_ref(), arena)); let tex2 = arena.alloc(convert_spectrum(t.tex2.as_ref(), arena)); let amount = arena.alloc(convert_float(t.amount.as_ref(), arena)); SpectrumTexture::Mix(SpectrumMixTexture { tex1, tex2, amount }) } HostSpectrumTexture::DirectionMix(t) => { let tex1 = arena.alloc(convert_spectrum(t.tex1.as_ref(), arena)); let tex2 = arena.alloc(convert_spectrum(t.tex2.as_ref(), arena)); SpectrumTexture::DirectionMix(SpectrumDirectionMixTexture { tex1, tex2, dir: t.dir, }) } HostSpectrumTexture::Image(t) => { let image = arena.alloc(t.base.mipmap.base_image().inner.clone()); let tex_obj = arena.get_texture_object(&t.base.mipmap); SpectrumTexture::Image(SpectrumImageTexture { image, tex_obj, wrap_mode: t.base.mipmap.wrap_mode, color_space: arena .alloc(t.base.mipmap.color_space.unwrap_or_else(default_colorspace)), mapping: t.base.mapping, scale: t.base.scale, invert: t.base.invert, is_single_channel: t.base.mipmap.is_single_channel(), spectrum_type: t.spectrum_type, }) } } } impl Upload for Arc { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_float(&self, arena)) } } impl Upload for Arc { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_spectrum(&self, arena)) } } impl Upload for &HostFloatTexture { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_float(self, arena)) } } impl Upload for &HostSpectrumTexture { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc(convert_spectrum(self, arena)) } } impl Upload for Option> { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc_opt(self.map(|v| convert_float(&v, arena))) } } impl Upload for Option> { type Target = Ptr; fn upload(self, arena: &Arena) -> Self::Target { arena.alloc_opt(self.map(|v| convert_spectrum(&v, arena))) } } impl Upload for HostImage { type Target = Ptr; fn upload(self, arena: &Arena) -> Ptr { arena.alloc(self.inner) } } impl Upload for Option { type Target = Ptr; fn upload(self, arena: &Arena) -> Ptr { arena.alloc_opt(self.map(|h| h.inner)) } } impl Upload for Option> { type Target = Ptr; fn upload(self, arena: &Arena) -> Ptr { arena.alloc_opt(self.map(|h| h.as_ref().inner.clone())) } } pub trait ArenaUpload { fn upload(&self, value: T) -> T::Target; } impl ArenaUpload for Arena { fn upload(&self, value: T) -> T::Target { value.upload(self) } }