mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Store Option<ImageInfo> instead of making fields optional
This commit is contained in:
parent
48d918dcde
commit
a4fa36f9fb
4 changed files with 47 additions and 69 deletions
|
@ -613,7 +613,7 @@ impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
|
||||||
compression,
|
compression,
|
||||||
} = self.compression_validator.validate()?;
|
} = self.compression_validator.validate()?;
|
||||||
|
|
||||||
let tex_info = texture.image_info_for_target(&target, level);
|
let tex_info = texture.image_info_for_target(&target, level).unwrap();
|
||||||
|
|
||||||
// GL_INVALID_VALUE is generated if:
|
// GL_INVALID_VALUE is generated if:
|
||||||
// - xoffset or yoffset is less than 0
|
// - xoffset or yoffset is less than 0
|
||||||
|
@ -630,7 +630,7 @@ impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
|
||||||
|
|
||||||
// GL_INVALID_OPERATION is generated if format does not match
|
// GL_INVALID_OPERATION is generated if format does not match
|
||||||
// internal_format.
|
// internal_format.
|
||||||
if compression.format != tex_info.internal_format().unwrap() {
|
if compression.format != tex_info.internal_format() {
|
||||||
context.webgl_error(InvalidOperation);
|
context.webgl_error(InvalidOperation);
|
||||||
return Err(TexImageValidationError::TextureFormatMismatch);
|
return Err(TexImageValidationError::TextureFormatMismatch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,12 +221,16 @@ impl WebGLFramebuffer {
|
||||||
Some(WebGLFramebufferAttachment::Texture {
|
Some(WebGLFramebufferAttachment::Texture {
|
||||||
texture: ref att_tex,
|
texture: ref att_tex,
|
||||||
level,
|
level,
|
||||||
}) => {
|
}) => match att_tex.image_info_at_face(0, level as u32) {
|
||||||
let info = att_tex.image_info_at_face(0, level as u32);
|
Some(info) => (
|
||||||
(
|
Some(info.internal_format().as_gl_constant()),
|
||||||
info.internal_format().map(|t| t.as_gl_constant()),
|
|
||||||
Some((info.width() as i32, info.height() as i32)),
|
Some((info.width() as i32, info.height() as i32)),
|
||||||
)
|
),
|
||||||
|
None => {
|
||||||
|
self.status
|
||||||
|
.set(constants::FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
|
||||||
|
return;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
None => (None, None),
|
None => (None, None),
|
||||||
};
|
};
|
||||||
|
|
|
@ -438,13 +438,12 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = TexImageTarget::Texture2D;
|
let target = TexImageTarget::Texture2D;
|
||||||
let info = texture.image_info_for_target(&target, 0);
|
if let Some(info) = texture.image_info_for_target(&target, 0) {
|
||||||
if info.is_initialized() {
|
|
||||||
self.validate_filterable_texture(
|
self.validate_filterable_texture(
|
||||||
&texture,
|
&texture,
|
||||||
target,
|
target,
|
||||||
0,
|
0,
|
||||||
info.internal_format().unwrap_or(TexFormat::RGBA),
|
info.internal_format(),
|
||||||
Size2D::new(info.width(), info.height()),
|
Size2D::new(info.width(), info.height()),
|
||||||
info.data_type().unwrap_or(TexDataType::UnsignedByte),
|
info.data_type().unwrap_or(TexDataType::UnsignedByte),
|
||||||
);
|
);
|
||||||
|
@ -746,7 +745,10 @@ impl WebGLRenderingContext {
|
||||||
pixels: TexPixels,
|
pixels: TexPixels,
|
||||||
) {
|
) {
|
||||||
// We have already validated level
|
// We have already validated level
|
||||||
let image_info = texture.image_info_for_target(&target, level);
|
let image_info = match texture.image_info_for_target(&target, level) {
|
||||||
|
Some(info) => info,
|
||||||
|
None => return self.webgl_error(InvalidOperation),
|
||||||
|
};
|
||||||
|
|
||||||
// GL_INVALID_VALUE is generated if:
|
// GL_INVALID_VALUE is generated if:
|
||||||
// - xoffset or yoffset is less than 0
|
// - xoffset or yoffset is less than 0
|
||||||
|
@ -761,9 +763,7 @@ impl WebGLRenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: format and internal_format must match.
|
// NB: format and internal_format must match.
|
||||||
if format != image_info.internal_format().unwrap() ||
|
if format != image_info.internal_format() || data_type != image_info.data_type().unwrap() {
|
||||||
data_type != image_info.data_type().unwrap()
|
|
||||||
{
|
|
||||||
return self.webgl_error(InvalidOperation);
|
return self.webgl_error(InvalidOperation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1921,9 +1921,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => {
|
Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => {
|
||||||
TexFormat::from_gl_constant(rb.internal_format())
|
TexFormat::from_gl_constant(rb.internal_format())
|
||||||
},
|
},
|
||||||
Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => {
|
Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => texture
|
||||||
texture.image_info_for_target(&target, 0).internal_format()
|
.image_info_for_target(&target, 0)
|
||||||
},
|
.map(|info| info.internal_format()),
|
||||||
None => None,
|
None => None,
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
|
@ -2022,7 +2022,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let image_info = texture.image_info_for_target(&target, level);
|
let image_info = match texture.image_info_for_target(&target, level) {
|
||||||
|
Some(info) => info,
|
||||||
|
None => return self.webgl_error(InvalidOperation),
|
||||||
|
};
|
||||||
|
|
||||||
// GL_INVALID_VALUE is generated if:
|
// GL_INVALID_VALUE is generated if:
|
||||||
// - xoffset or yoffset is less than 0
|
// - xoffset or yoffset is less than 0
|
||||||
|
|
|
@ -40,7 +40,7 @@ pub struct WebGLTexture {
|
||||||
is_deleted: Cell<bool>,
|
is_deleted: Cell<bool>,
|
||||||
/// Stores information about mipmap levels and cubemap faces.
|
/// Stores information about mipmap levels and cubemap faces.
|
||||||
#[ignore_malloc_size_of = "Arrays are cumbersome"]
|
#[ignore_malloc_size_of = "Arrays are cumbersome"]
|
||||||
image_info_array: DomRefCell<[ImageInfo; MAX_LEVEL_COUNT * MAX_FACE_COUNT]>,
|
image_info_array: DomRefCell<[Option<ImageInfo>; MAX_LEVEL_COUNT * MAX_FACE_COUNT]>,
|
||||||
/// Face count can only be 1 or 6
|
/// Face count can only be 1 or 6
|
||||||
face_count: Cell<u8>,
|
face_count: Cell<u8>,
|
||||||
base_mipmap_level: u32,
|
base_mipmap_level: u32,
|
||||||
|
@ -64,7 +64,7 @@ impl WebGLTexture {
|
||||||
base_mipmap_level: 0,
|
base_mipmap_level: 0,
|
||||||
min_filter: Cell::new(constants::NEAREST_MIPMAP_LINEAR),
|
min_filter: Cell::new(constants::NEAREST_MIPMAP_LINEAR),
|
||||||
mag_filter: Cell::new(constants::LINEAR),
|
mag_filter: Cell::new(constants::LINEAR),
|
||||||
image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
|
image_info_array: DomRefCell::new([None; MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
|
||||||
attached_to_dom: Cell::new(false),
|
attached_to_dom: Cell::new(false),
|
||||||
attached_framebuffer: Default::default(),
|
attached_framebuffer: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -135,8 +135,7 @@ impl WebGLTexture {
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
depth: depth,
|
depth: depth,
|
||||||
internal_format: Some(internal_format),
|
internal_format: internal_format,
|
||||||
is_initialized: true,
|
|
||||||
data_type: data_type,
|
data_type: data_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,10 +158,7 @@ impl WebGLTexture {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let base_image_info = self.base_image_info();
|
let base_image_info = self.base_image_info().ok_or(WebGLError::InvalidOperation)?;
|
||||||
if !base_image_info.is_initialized() {
|
|
||||||
return Err(WebGLError::InvalidOperation);
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_cubic = target == constants::TEXTURE_CUBE_MAP;
|
let is_cubic = target == constants::TEXTURE_CUBE_MAP;
|
||||||
if is_cubic && !self.is_cube_complete() {
|
if is_cubic && !self.is_cube_complete() {
|
||||||
|
@ -308,10 +304,9 @@ impl WebGLTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn populate_mip_chain(&self, first_level: u32, last_level: u32) -> WebGLResult<()> {
|
pub fn populate_mip_chain(&self, first_level: u32, last_level: u32) -> WebGLResult<()> {
|
||||||
let base_image_info = self.image_info_at_face(0, first_level);
|
let base_image_info = self
|
||||||
if !base_image_info.is_initialized() {
|
.image_info_at_face(0, first_level)
|
||||||
return Err(WebGLError::InvalidOperation);
|
.ok_or(WebGLError::InvalidOperation)?;
|
||||||
}
|
|
||||||
|
|
||||||
let mut ref_width = base_image_info.width;
|
let mut ref_width = base_image_info.width;
|
||||||
let mut ref_height = base_image_info.height;
|
let mut ref_height = base_image_info.height;
|
||||||
|
@ -333,7 +328,6 @@ impl WebGLTexture {
|
||||||
height: ref_height,
|
height: ref_height,
|
||||||
depth: 0,
|
depth: 0,
|
||||||
internal_format: base_image_info.internal_format,
|
internal_format: base_image_info.internal_format,
|
||||||
is_initialized: base_image_info.is_initialized(),
|
|
||||||
data_type: base_image_info.data_type,
|
data_type: base_image_info.data_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -345,19 +339,19 @@ impl WebGLTexture {
|
||||||
fn is_cube_complete(&self) -> bool {
|
fn is_cube_complete(&self) -> bool {
|
||||||
debug_assert_eq!(self.face_count.get(), 6);
|
debug_assert_eq!(self.face_count.get(), 6);
|
||||||
|
|
||||||
let image_info = self.base_image_info();
|
let image_info = match self.base_image_info() {
|
||||||
if !image_info.is_defined() {
|
Some(info) => info,
|
||||||
return false;
|
None => return false,
|
||||||
}
|
};
|
||||||
|
|
||||||
let ref_width = image_info.width;
|
let ref_width = image_info.width;
|
||||||
let ref_format = image_info.internal_format;
|
let ref_format = image_info.internal_format;
|
||||||
|
|
||||||
for face in 0..self.face_count.get() {
|
for face in 0..self.face_count.get() {
|
||||||
let current_image_info = self.image_info_at_face(face, self.base_mipmap_level);
|
let current_image_info = match self.image_info_at_face(face, self.base_mipmap_level) {
|
||||||
if !current_image_info.is_defined() {
|
Some(info) => info,
|
||||||
return false;
|
None => return false,
|
||||||
}
|
};
|
||||||
|
|
||||||
// Compares height with width to enforce square dimensions
|
// Compares height with width to enforce square dimensions
|
||||||
if current_image_info.internal_format != ref_format ||
|
if current_image_info.internal_format != ref_format ||
|
||||||
|
@ -383,12 +377,12 @@ impl WebGLTexture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn image_info_for_target(&self, target: &TexImageTarget, level: u32) -> ImageInfo {
|
pub fn image_info_for_target(&self, target: &TexImageTarget, level: u32) -> Option<ImageInfo> {
|
||||||
let face_index = self.face_index_for_target(&target);
|
let face_index = self.face_index_for_target(&target);
|
||||||
self.image_info_at_face(face_index, level)
|
self.image_info_at_face(face_index, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo {
|
pub fn image_info_at_face(&self, face: u8, level: u32) -> Option<ImageInfo> {
|
||||||
let pos = (level * self.face_count.get() as u32) + face as u32;
|
let pos = (level * self.face_count.get() as u32) + face as u32;
|
||||||
self.image_info_array.borrow()[pos as usize]
|
self.image_info_array.borrow()[pos as usize]
|
||||||
}
|
}
|
||||||
|
@ -402,10 +396,10 @@ impl WebGLTexture {
|
||||||
fn set_image_infos_at_level_and_face(&self, level: u32, face: u8, image_info: ImageInfo) {
|
fn set_image_infos_at_level_and_face(&self, level: u32, face: u8, image_info: ImageInfo) {
|
||||||
debug_assert!(face < self.face_count.get());
|
debug_assert!(face < self.face_count.get());
|
||||||
let pos = (level * self.face_count.get() as u32) + face as u32;
|
let pos = (level * self.face_count.get() as u32) + face as u32;
|
||||||
self.image_info_array.borrow_mut()[pos as usize] = image_info;
|
self.image_info_array.borrow_mut()[pos as usize] = Some(image_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base_image_info(&self) -> ImageInfo {
|
fn base_image_info(&self) -> Option<ImageInfo> {
|
||||||
assert!((self.base_mipmap_level as usize) < MAX_LEVEL_COUNT);
|
assert!((self.base_mipmap_level as usize) < MAX_LEVEL_COUNT);
|
||||||
|
|
||||||
self.image_info_at_face(0, self.base_mipmap_level)
|
self.image_info_at_face(0, self.base_mipmap_level)
|
||||||
|
@ -435,23 +429,11 @@ pub struct ImageInfo {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
depth: u32,
|
depth: u32,
|
||||||
internal_format: Option<TexFormat>,
|
internal_format: TexFormat,
|
||||||
is_initialized: bool,
|
|
||||||
data_type: Option<TexDataType>,
|
data_type: Option<TexDataType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageInfo {
|
impl ImageInfo {
|
||||||
fn new() -> ImageInfo {
|
|
||||||
ImageInfo {
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
depth: 0,
|
|
||||||
internal_format: None,
|
|
||||||
is_initialized: false,
|
|
||||||
data_type: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn width(&self) -> u32 {
|
pub fn width(&self) -> u32 {
|
||||||
self.width
|
self.width
|
||||||
}
|
}
|
||||||
|
@ -460,7 +442,7 @@ impl ImageInfo {
|
||||||
self.height
|
self.height
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn internal_format(&self) -> Option<TexFormat> {
|
pub fn internal_format(&self) -> TexFormat {
|
||||||
self.internal_format
|
self.internal_format
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,14 +456,6 @@ impl ImageInfo {
|
||||||
self.depth.is_power_of_two()
|
self.depth.is_power_of_two()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_initialized(&self) -> bool {
|
|
||||||
self.is_initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_defined(&self) -> bool {
|
|
||||||
self.internal_format.is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_max_mimap_levels(&self) -> u32 {
|
fn get_max_mimap_levels(&self) -> u32 {
|
||||||
let largest = cmp::max(cmp::max(self.width, self.height), self.depth);
|
let largest = cmp::max(cmp::max(self.width, self.height), self.depth);
|
||||||
if largest == 0 {
|
if largest == 0 {
|
||||||
|
@ -492,10 +466,7 @@ impl ImageInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_compressed_format(&self) -> bool {
|
fn is_compressed_format(&self) -> bool {
|
||||||
match self.internal_format {
|
self.internal_format.is_compressed()
|
||||||
Some(format) => format.is_compressed(),
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue