1use crate::{
7 enums::{CreateStorage, TextureCreateFlags},
8 stream::{RWSeekable, RustKtxStream},
9 sys::{self},
10 texture::{Texture, TextureSource},
11 KtxError,
12};
13use std::{
14 convert::TryInto,
15 marker::PhantomData,
16 sync::{Arc, Mutex},
17};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct CommonCreateInfo {
22 pub create_storage: CreateStorage,
23 pub base_width: u32,
24 pub base_height: u32,
25 pub base_depth: u32,
26 pub num_dimensions: u32,
27 pub num_levels: u32,
28 pub num_layers: u32,
29 pub num_faces: u32,
30 pub is_array: bool,
31 pub generate_mipmaps: bool,
32}
33
34impl Default for CommonCreateInfo {
35 fn default() -> Self {
36 CommonCreateInfo {
37 create_storage: CreateStorage::AllocStorage,
38 base_width: 1,
39 base_height: 1,
40 base_depth: 1,
41 num_dimensions: 1,
42 num_levels: 1,
43 num_layers: 1,
44 num_faces: 1,
45 is_array: false,
46 generate_mipmaps: false,
47 }
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct Ktx1CreateInfo {
55 pub gl_internal_format: u32,
56 pub common: CommonCreateInfo,
57}
58
59impl Default for Ktx1CreateInfo {
60 fn default() -> Self {
61 Ktx1CreateInfo {
62 gl_internal_format: 0x8058, common: Default::default(),
64 }
65 }
66}
67
68fn try_create_texture<'a, S, C>(source: S, create_fn: C) -> Result<Texture<'a>, KtxError>
69where
70 S: TextureSource<'a> + 'a,
71 C: FnOnce(S) -> (S, sys::ktx_error_code_e, *mut sys::ktxTexture),
72{
73 let (source, err, handle) = (create_fn)(source);
74 if err == sys::ktx_error_code_e_KTX_SUCCESS && !handle.is_null() {
75 Ok(Texture {
76 source: Box::new(source),
77 handle,
78 handle_phantom: PhantomData,
79 })
80 } else {
81 Err(err.try_into().unwrap_or(KtxError::InvalidOperation))
82 }
83}
84
85impl<'a> TextureSource<'a> for Ktx1CreateInfo {
86 fn create_texture(self) -> Result<Texture<'a>, KtxError> {
87 let mut sys_create_info = sys::ktxTextureCreateInfo {
88 glInternalformat: self.gl_internal_format,
89 vkFormat: 0,
90 pDfd: std::ptr::null_mut(),
91 baseWidth: self.common.base_width,
92 baseHeight: self.common.base_height,
93 baseDepth: self.common.base_depth,
94 numDimensions: self.common.num_dimensions,
95 numLevels: self.common.num_levels,
96 numLayers: self.common.num_layers,
97 numFaces: self.common.num_faces,
98 isArray: self.common.is_array,
99 generateMipmaps: self.common.generate_mipmaps,
100 };
101
102 try_create_texture(self, |source| {
103 let mut handle: *mut sys::ktxTexture = std::ptr::null_mut();
104 let handle_ptr: *mut *mut sys::ktxTexture = &mut handle;
105
106 let err = unsafe {
107 sys::ktxTexture1_Create(
108 &mut sys_create_info,
109 source.common.create_storage as u32,
110 handle_ptr as *mut *mut sys::ktxTexture1,
111 )
112 };
113 (source, err, handle)
114 })
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
121pub struct Ktx2CreateInfo {
122 pub vk_format: u32,
123 pub dfd: Option<Vec<u32>>,
124 pub common: CommonCreateInfo,
125}
126
127impl Default for Ktx2CreateInfo {
128 fn default() -> Self {
129 Ktx2CreateInfo {
130 vk_format: 37, dfd: None,
132 common: Default::default(),
133 }
134 }
135}
136
137impl<'a> TextureSource<'a> for Ktx2CreateInfo {
138 fn create_texture(mut self) -> Result<Texture<'a>, KtxError> {
139 let dfd_ptr = match &mut self.dfd {
144 Some(dfd_data) => dfd_data.as_mut_ptr() as *mut u32,
145 None => std::ptr::null_mut(),
146 };
147
148 let mut sys_create_info = sys::ktxTextureCreateInfo {
149 glInternalformat: 0,
150 vkFormat: self.vk_format,
151 pDfd: dfd_ptr,
152 baseWidth: self.common.base_width,
153 baseHeight: self.common.base_height,
154 baseDepth: self.common.base_depth,
155 numDimensions: self.common.num_dimensions,
156 numLevels: self.common.num_levels,
157 numLayers: self.common.num_layers,
158 numFaces: self.common.num_faces,
159 isArray: self.common.is_array,
160 generateMipmaps: self.common.generate_mipmaps,
161 };
162
163 try_create_texture(self, |source| {
164 let mut handle: *mut sys::ktxTexture = std::ptr::null_mut();
165 let handle_ptr: *mut *mut sys::ktxTexture = &mut handle;
166
167 let err = unsafe {
168 sys::ktxTexture2_Create(
169 &mut sys_create_info,
170 source.common.create_storage as u32,
171 handle_ptr as *mut *mut sys::ktxTexture2,
172 )
173 };
174 (source, err, handle)
175 })
176 }
177}
178
179#[derive(Debug)]
181pub struct StreamSource<'a, T: RWSeekable + ?Sized + 'a> {
182 stream: Arc<Mutex<RustKtxStream<'a, T>>>,
183 texture_create_flags: TextureCreateFlags,
184}
185
186impl<'a, T: RWSeekable + ?Sized + 'a> StreamSource<'a, T> {
187 pub fn new(
189 inner: Arc<Mutex<RustKtxStream<'a, T>>>,
190 texture_create_flags: TextureCreateFlags,
191 ) -> Self {
192 StreamSource {
193 stream: inner,
194 texture_create_flags,
195 }
196 }
197
198 pub fn into_inner(self) -> Arc<Mutex<RustKtxStream<'a, T>>> {
200 self.stream
201 }
202}
203
204impl<'a, T: RWSeekable + ?Sized + 'a> TextureSource<'a> for StreamSource<'a, T> {
205 fn create_texture(self) -> Result<Texture<'a>, KtxError> {
206 try_create_texture(self, |source| {
207 let mut handle: *mut sys::ktxTexture = std::ptr::null_mut();
208 let handle_ptr: *mut *mut sys::ktxTexture = &mut handle;
209
210 let err = unsafe {
211 sys::ktxTexture_CreateFromStream(
212 source
213 .stream
214 .lock()
215 .expect("Inner stream is poisoned")
216 .ktx_stream(),
217 source.texture_create_flags.bits(),
218 handle_ptr,
219 )
220 };
221 (source, err, handle)
222 })
223 }
224}