1use std::error::Error;
25use std::{fmt, cmp, hash};
26use memory::{Bind, Usage};
27use {format, state, target, Resources};
28pub use target::{Layer, Level};
29
30pub const MAX_LEVEL: Level = 15;
32
33#[derive(Debug)]
35pub struct Raw<R: Resources> {
36 resource: R::Texture,
37 info: Info,
38}
39
40impl<R: Resources> Raw<R> {
41 #[doc(hidden)]
42 pub fn new(resource: R::Texture, info: Info) -> Self {
43 Raw {
44 resource: resource,
45 info: info,
46 }
47 }
48
49 #[doc(hidden)]
50 pub fn resource(&self) -> &R::Texture { &self.resource }
51
52 pub fn get_info(&self) -> &Info { &self.info }
54}
55
56impl<R: Resources + cmp::PartialEq> cmp::PartialEq for Raw<R> {
57 fn eq(&self, other: &Self) -> bool {
58 self.resource().eq(other.resource())
59 }
60}
61
62impl<R: Resources + cmp::Eq> cmp::Eq for Raw<R> {}
63
64impl<R: Resources + hash::Hash> hash::Hash for Raw<R> {
65 fn hash<H: hash::Hasher>(&self, state: &mut H) {
66 self.resource().hash(state);
67 }
68}
69
70#[derive(Clone, Copy, Debug, PartialEq)]
72pub enum CreationError {
73 Format(format::SurfaceType, Option<format::ChannelType>),
75 Kind,
77 Samples(AaMode),
79 Size(Size),
81 Data(usize),
83 Usage(Usage),
85 Mipmap,
87 Level(Level),
89}
90
91impl fmt::Display for CreationError {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93 match *self {
94 CreationError::Format(surf, chan) => write!(f, "{}: ({:?}, {:?})",
95 self.description(), surf, chan),
96 CreationError::Samples(aa) => write!(f, "{}: {:?}", self.description(), aa),
97 CreationError::Size(size) => write!(f, "{}: {}", self.description(), size),
98 CreationError::Data(data) => write!(f, "{}: {}", self.description(), data),
99 CreationError::Usage(usage) => write!(f, "{}: {:?}", self.description(), usage),
100 _ => write!(f, "{}", self.description()),
101 }
102 }
103}
104
105impl Error for CreationError {
106 fn description(&self) -> &str {
107 match *self {
108 CreationError::Format(..) => "Failed to map a given format to the device",
109 CreationError::Kind => "The kind doesn't support a particular operation",
110 CreationError::Samples(_) => "Failed to map a given multisampled kind to the device",
111 CreationError::Size(_) => "Unsupported size in one of the dimensions",
112 CreationError::Data(_) => "The given data has a different size than the target texture slice",
113 CreationError::Usage(_) => "The expected texture usage mode is not supported by a graphic API",
114 CreationError::Mipmap => "The requested mipmap creation parameter is unsupported",
115 CreationError::Level(_) => "The requested mipmap level count does not match the provided data",
116 }
117 }
118}
119
120#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
122pub enum LayerError {
123 NotExpected(Kind),
125 OutOfBounds(target::Layer, target::Layer),
127}
128
129impl fmt::Display for LayerError {
130 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131 match *self {
132 LayerError::NotExpected(kind) => write!(f, "{}: {:?}", self.description(), kind),
133 LayerError::OutOfBounds(layer, count) => write!(f, "{}: {}/{}", self.description(), layer, count),
134 }
135 }
136}
137
138impl Error for LayerError {
139 fn description(&self) -> &str {
140 match *self {
141 LayerError::NotExpected(_) => "The source texture kind doesn't support array slices",
142 LayerError::OutOfBounds(_, _) => "Selected layer is outside of the provided range",
143 }
144 }
145}
146
147pub type Size = u16;
149pub type Bits = u8;
151pub type NumSamples = u8;
153pub type NumFragments = u8;
155
156pub type Dimensions = (Size, Size, Size, AaMode);
158
159#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
161#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
162pub enum AaMode {
163 Single,
165 Multi(NumSamples),
167 Coverage(NumSamples, NumFragments),
169}
170
171impl From<NumSamples> for AaMode {
172 fn from(ns: NumSamples) -> AaMode {
173 if ns > 1 {
174 AaMode::Multi(ns)
175 } else {
176 AaMode::Single
177 }
178 }
179}
180
181impl AaMode {
182 pub fn get_num_fragments(&self) -> NumFragments {
184 match *self {
185 AaMode::Single => 1,
186 AaMode::Multi(n) => n,
187 AaMode::Coverage(_, nf) => nf,
188 }
189 }
190 pub fn needs_resolve(&self) -> bool {
192 self.get_num_fragments() > 1
193 }
194}
195
196
197#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
208#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
209pub enum FilterMethod {
210 Scale,
212 Mipmap,
214 Bilinear,
217 Trilinear,
219 Anisotropic(u8)
222}
223
224#[allow(missing_docs)]
226#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
227#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
228#[repr(u8)]
229pub enum CubeFace {
230 PosX,
231 NegX,
232 PosY,
233 NegY,
234 PosZ,
235 NegZ,
236}
237
238pub const CUBE_FACES: [CubeFace; 6] = [
240 CubeFace::PosX, CubeFace::NegX,
241 CubeFace::PosY, CubeFace::NegY,
242 CubeFace::PosZ, CubeFace::NegZ,
243];
244
245#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
247#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
248pub enum Kind {
249 D1(Size),
251 D1Array(Size, Layer),
254 D2(Size, Size, AaMode),
256 D2Array(Size, Size, Layer, AaMode),
259 D3(Size, Size, Size),
261 Cube(Size),
263 CubeArray(Size, Layer),
265}
266
267impl Kind {
268 pub fn get_dimensions(&self) -> Dimensions {
270 let s0 = AaMode::Single;
271 match *self {
272 Kind::D1(w) => (w, 1, 1, s0),
273 Kind::D1Array(w, a) => (w, 1, a as Size, s0),
274 Kind::D2(w, h, s) => (w, h, 1, s),
275 Kind::D2Array(w, h, a, s) => (w, h, a as Size, s),
276 Kind::D3(w, h, d) => (w, h, d, s0),
277 Kind::Cube(w) => (w, w, 6, s0),
278 Kind::CubeArray(w, a) => (w, w, 6 * (a as Size), s0)
279 }
280 }
281 pub fn get_level_dimensions(&self, level: Level) -> Dimensions {
283 use std::cmp::{max, min};
284 let map = |val| max(min(val, 1), val >> min(level, MAX_LEVEL));
286 let (w, h, da, _) = self.get_dimensions();
287 (map(w), map(h), map(da), AaMode::Single)
288 }
289 pub fn get_num_levels(&self) -> Level {
291 use std::cmp::max;
292 let (w, h, d, aa) = self.get_dimensions();
293 let dominant = max(max(w, h), d);
294 if aa == AaMode::Single {
295 (1..).find(|level| dominant>>level <= 1).unwrap()
296 }else {
297 1 }
299 }
300 pub fn get_num_slices(&self) -> Option<Layer> {
302 match *self {
303 Kind::D1(..) | Kind::D2(..) | Kind::D3(..) | Kind::Cube(..) => None,
304 Kind::D1Array(_, a) => Some(a),
305 Kind::D2Array(_, _, a, _) => Some(a),
306 Kind::CubeArray(_, a) => Some(a),
307 }
308 }
309 pub fn is_cube(&self) -> bool {
311 match *self {
312 Kind::Cube(_) | Kind::CubeArray(_, _) => true,
313 _ => false,
314 }
315 }
316}
317
318#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
320#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
321#[repr(u8)]
322pub enum Mipmap {
323 Provided,
325 Allocated, }
329
330#[allow(missing_docs)]
332#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
333#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
334pub struct ImageInfoCommon<F> {
335 pub xoffset: Size,
336 pub yoffset: Size,
337 pub zoffset: Size,
338 pub width: Size,
339 pub height: Size,
340 pub depth: Size,
341 pub format: F,
343 pub mipmap: Level,
345}
346
347pub type RawImageInfo = ImageInfoCommon<format::Format>;
349pub type NewImageInfo = ImageInfoCommon<()>;
353
354impl<F> ImageInfoCommon<F> {
355 pub fn get_texel_count(&self) -> usize {
357 use std::cmp::max;
358 max(1, self.width) as usize *
359 max(1, self.height) as usize *
360 max(1, self.depth) as usize
361 }
362
363 pub fn convert<T>(&self, new_format: T) -> ImageInfoCommon<T> {
365 ImageInfoCommon {
366 xoffset: self.xoffset,
367 yoffset: self.yoffset,
368 zoffset: self.zoffset,
369 width: self.width,
370 height: self.height,
371 depth: self.depth,
372 format: new_format,
373 mipmap: self.mipmap,
374 }
375 }
376
377 pub fn is_inside(&self, (w, h, d, aa): Dimensions) -> bool {
379 aa == AaMode::Single &&
380 self.xoffset + self.width <= w &&
381 self.yoffset + self.height <= h &&
382 self.zoffset + self.depth <= d
383 }
384}
385
386impl RawImageInfo {
387 pub fn get_byte_count(&self) -> usize {
389 let texel_bytes = self.format.0.get_total_bits() / 8;
390 self.get_texel_count() * (texel_bytes as usize)
391 }
392}
393
394#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
396#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
397pub struct TextureCopyRegion<T> {
398 pub texture: T,
400 pub kind: Kind,
402 pub cube_face: Option<CubeFace>,
404 pub info: RawImageInfo,
406}
407
408impl<T> TextureCopyRegion<T> {
409 pub fn with_texture<U>(self, texture: U) -> TextureCopyRegion<U> {
411 TextureCopyRegion {
412 texture,
413 kind: self.kind,
414 cube_face: self.cube_face,
415 info: self.info,
416 }
417 }
418}
419
420#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
422#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
423pub enum WrapMode {
424 Tile,
427 Mirror,
429 Clamp,
431 Border,
433}
434
435#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
437#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
438pub struct Lod(i16);
439
440impl From<f32> for Lod {
441 fn from(v: f32) -> Lod {
442 Lod((v * 8.0) as i16)
443 }
444}
445
446impl Into<f32> for Lod {
447 fn into(self) -> f32 {
448 self.0 as f32 / 8.0
449 }
450}
451
452#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
454#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
455pub struct PackedColor(pub u32);
456
457impl From<[f32; 4]> for PackedColor {
458 fn from(c: [f32; 4]) -> PackedColor {
459 PackedColor(c.iter().rev().fold(0, |u, &c| {
460 (u<<8) + (c * 255.0) as u32
461 }))
462 }
463}
464
465impl Into<[f32; 4]> for PackedColor {
466 fn into(self) -> [f32; 4] {
467 let mut out = [0.0; 4];
468 for i in 0 .. 4 {
469 let byte = (self.0 >> (i<<3)) & 0xFF;
470 out[i] = byte as f32 / 255.0;
471 }
472 out
473 }
474}
475
476#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd)]
479#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
480pub struct SamplerInfo {
481 pub filter: FilterMethod,
483 pub wrap_mode: (WrapMode, WrapMode, WrapMode),
486 #[cfg_attr(feature = "serialize", serde(default = "SamplerInfo::def_lod_bias"))]
490 pub lod_bias: Lod,
491 #[cfg_attr(feature = "serialize", serde(default = "SamplerInfo::def_lod_range"))]
493 pub lod_range: (Lod, Lod),
494 #[cfg_attr(feature = "serialize", serde(default))]
496 pub comparison: Option<state::Comparison>,
497 #[cfg_attr(feature = "serialize", serde(default = "SamplerInfo::def_border"))]
499 pub border: PackedColor,
500}
501
502impl SamplerInfo {
503 pub fn new(filter: FilterMethod, wrap: WrapMode) -> SamplerInfo {
506 SamplerInfo {
507 filter: filter,
508 wrap_mode: (wrap, wrap, wrap),
509 lod_bias: Self::def_lod_bias(),
510 lod_range: Self::def_lod_range(),
511 comparison: None,
512 border: Self::def_border(),
513 }
514 }
515
516 fn def_lod_bias() -> Lod {
517 Lod(0)
518 }
519
520 fn def_lod_range() -> (Lod, Lod) {
521 (Lod(-8000), Lod(8000))
522 }
523
524 fn def_border() -> PackedColor {
525 PackedColor(0)
526 }
527}
528
529#[allow(missing_docs)]
531#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
532#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
533pub struct Info {
534 pub kind: Kind,
535 pub levels: Level,
536 pub format: format::SurfaceType,
537 pub bind: Bind,
538 pub usage: Usage,
539}
540
541impl Info {
542 pub fn to_image_info(&self, mip: Level) -> NewImageInfo {
544 let (w, h, d, _) = self.kind.get_level_dimensions(mip);
545 ImageInfoCommon {
546 xoffset: 0,
547 yoffset: 0,
548 zoffset: 0,
549 width: w,
550 height: h,
551 depth: d,
552 format: (),
553 mipmap: mip,
554 }
555 }
556
557 pub fn to_raw_image_info(&self, cty: format::ChannelType, mip: Level) -> RawImageInfo {
559 let format = format::Format(self.format, cty.into());
560 self.to_image_info(mip).convert(format)
561 }
562}
563
564#[allow(missing_docs)]
566#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
567#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
568pub struct ResourceDesc {
569 pub channel: format::ChannelType,
570 pub layer: Option<Layer>,
571 pub min: Level,
572 pub max: Level,
573 pub swizzle: format::Swizzle,
574}
575
576#[allow(missing_docs)]
578#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
579#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
580pub struct RenderDesc {
581 pub channel: format::ChannelType,
582 pub level: Level,
583 pub layer: Option<Layer>,
584}
585
586bitflags!(
587 #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
589 pub struct DepthStencilFlags: u8 {
590 const RO_DEPTH = 0x1;
592 const RO_STENCIL = 0x2;
594 const RO_DEPTH_STENCIL = 0x3;
596 }
597);
598
599#[allow(missing_docs)]
601#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
602#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
603pub struct DepthStencilDesc {
604 pub level: Level,
605 pub layer: Option<Layer>,
606 pub flags: DepthStencilFlags,
607}
608
609impl From<RenderDesc> for DepthStencilDesc {
610 fn from(rd: RenderDesc) -> DepthStencilDesc {
611 DepthStencilDesc {
612 level: rd.level,
613 layer: rd.layer,
614 flags: DepthStencilFlags::empty(),
615 }
616 }
617}