Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes for a couple of panics in WR. #218

Merged
merged 1 commit into from Mar 3, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -1155,38 +1155,49 @@ impl Device {
}

pub fn resize_texture(&mut self,
new_texture_id: TextureId,
old_texture_id: TextureId,
width: u32,
height: u32,
texture_id: TextureId,
new_width: u32,
new_height: u32,
format: ImageFormat,
filter: TextureFilter,
mode: RenderTargetMode) {
debug_assert!(self.inside_frame);

self.init_texture(new_texture_id, width, height, format, filter, mode, None);
let (old_width, old_height) = self.get_texture_dimensions(texture_id);

self.create_fbo_for_texture_if_necessary(old_texture_id);
self.bind_render_target(Some(old_texture_id));
self.bind_color_texture(new_texture_id);
let temp_texture_id = self.create_texture_ids(1)[0];
self.init_texture(temp_texture_id, old_width, old_height, format, filter, mode, None);
self.create_fbo_for_texture_if_necessary(temp_texture_id);

{
let old_texture = self.textures
.get(&old_texture_id)
.expect("Didn't find old texture ID in texture map?!");

gl::copy_tex_sub_image_2d(gl::TEXTURE_2D,
0,
0,
0,
0,
0,
old_texture.width as i32,
old_texture.height as i32);
}
self.bind_render_target(Some(texture_id));
self.bind_color_texture(temp_texture_id);

gl::copy_tex_sub_image_2d(gl::TEXTURE_2D,
0,
0,
0,
0,
0,
old_width as i32,
old_height as i32);

self.deinit_texture(texture_id);
self.init_texture(texture_id, new_width, new_height, format, filter, mode, None);
self.create_fbo_for_texture_if_necessary(texture_id);
self.bind_render_target(Some(temp_texture_id));
self.bind_color_texture(texture_id);

gl::copy_tex_sub_image_2d(gl::TEXTURE_2D,
0,
0,
0,
0,
0,
old_width as i32,
old_height as i32);

self.bind_render_target(None);
self.deinit_texture(old_texture_id);
self.deinit_texture(temp_texture_id);
}

pub fn deinit_texture(&mut self, texture_id: TextureId) {
@@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::collections::HashSet;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct FreeListItemId(u32);

@@ -98,71 +100,22 @@ impl<T: FreeListItem> FreeList<T> {
self.first_free_index = Some(id);
}

/// NB: This iterates over free items too!
pub fn iter_mut(&mut self) -> IterMut<T> {
let first_free_index = self.first_free_index;
let mut iterator = IterMut {
free_list: self,
next_index: Some(FreeListItemId(0)),
next_free_index: first_free_index,
};
iterator.advance_past_free_indices();
iterator
}
}
pub fn for_each_item<F>(&mut self, f: F) where F: Fn(&mut T) {
let mut free_ids = HashSet::new();

pub struct IterMut<'a, T> where T: FreeListItem + 'a {
free_list: &'a mut FreeList<T>,
next_index: Option<FreeListItemId>,
next_free_index: Option<FreeListItemId>,
}
let mut next_free_id = self.first_free_index;
while let Some(free_id) = next_free_id {
free_ids.insert(free_id);
let FreeListItemId(index) = free_id;
let free_item = &self.items[index as usize];
next_free_id = free_item.next_free_id();
}

impl<'a, T> IterMut<'a, T> where T: FreeListItem + 'a {
fn advance_past_free_indices(&mut self) {
loop {
let next_index = match self.next_index {
None => return,
Some(next_index) => next_index.0 as usize,
};
if next_index == self.free_list.items.len() {
self.next_index = None;
return
}
let next_free_index = match self.next_free_index {
None => return,
Some(next_free_index) => next_free_index.0 as usize,
};
if next_index == next_free_index {
self.next_index = Some(FreeListItemId(next_index as u32 + 1));
continue
}
if next_free_index < next_index {
self.next_free_index = self.free_list
.items[next_free_index]
.next_free_id();
continue
for (index, mut item) in self.items.iter_mut().enumerate() {
let id = FreeListItemId(index as u32);
if !free_ids.contains(&id) {
f(&mut item);
}
debug_assert!(next_free_index > next_index);
break
}
}

pub fn free_list(&mut self) -> &mut FreeList<T> {
self.free_list
}
}

impl<'a, T> Iterator for IterMut<'a, T> where T: FreeListItem + 'a {
type Item = FreeListItemId;

fn next(&mut self) -> Option<FreeListItemId> {
let next_index = match self.next_index {
None => return None,
Some(next_index) => next_index,
};
self.next_index = Some(FreeListItemId(next_index.0 + 1));
self.advance_past_free_indices();
Some(next_index)
}
}

@@ -376,7 +376,7 @@ pub struct TextureImage {
pub enum TextureUpdateOp {
Create(u32, u32, ImageFormat, TextureFilter, RenderTargetMode, Option<Vec<u8>>),
Update(u32, u32, u32, u32, TextureUpdateDetails),
Grow(TextureId, u32, u32, ImageFormat, TextureFilter, RenderTargetMode),
Grow(u32, u32, ImageFormat, TextureFilter, RenderTargetMode),
}

pub struct TextureUpdate {
@@ -504,14 +504,12 @@ impl Renderer {
}
}
}
TextureUpdateOp::Grow(old_texture_id,
new_width,
TextureUpdateOp::Grow(new_width,
new_height,
format,
filter,
mode) => {
self.device.resize_texture(update.id,
old_texture_id,
new_width,
new_height,
format,
@@ -349,14 +349,13 @@ impl TexturePage {
self.dirty = true
}

fn grow(&mut self, new_texture_id: TextureId, new_texture_size: u32) {
fn grow(&mut self, new_texture_size: u32) {
self.free_list.push(&Rect::new(Point2D::new(self.texture_size, 0),
Size2D::new(new_texture_size - self.texture_size,
new_texture_size)));
self.free_list.push(&Rect::new(Point2D::new(0, self.texture_size),
Size2D::new(self.texture_size,
new_texture_size - self.texture_size)));
self.texture_id = new_texture_id;
self.texture_size = new_texture_size
}

@@ -805,33 +804,15 @@ impl TextureCache {
// Grow the texture.
let texture_size = cmp::min(last_page.texture_size * 2,
max_texture_size());
let new_texture_id =
self.free_texture_ids
.pop()
.expect("TODO: Handle running out of texture IDs!");
self.pending_updates.push(TextureUpdate {
id: new_texture_id,
op: texture_grow_op(last_page.texture_id, texture_size, format, mode),
id: last_page.texture_id,
op: texture_grow_op(texture_size, format, mode),
});
let old_texture_id = last_page.texture_id;
last_page.grow(new_texture_id, texture_size);

{
let mut iter = self.items.iter_mut();
while let Some(id) = iter.next() {
let item = iter.free_list().get_mut(id);
if item.texture_id == old_texture_id {
item.texture_id = new_texture_id;
item.texture_size = Size2D::new(texture_size, texture_size);
}
}
}
last_page.grow(texture_size);

for update in &mut self.pending_updates.updates {
if update.id == old_texture_id {
update.id = new_texture_id
}
}
self.items.for_each_item(|item| {
item.texture_size = Size2D::new(texture_size, texture_size);
});
} else {
// We need a new page.
let texture_size = initial_texture_size();
@@ -1211,13 +1192,11 @@ fn texture_create_op(texture_size: u32, format: ImageFormat, mode: RenderTargetM
TextureUpdateOp::Create(texture_size, texture_size, format, TextureFilter::Linear, mode, None)
}

fn texture_grow_op(old_texture_id: TextureId,
texture_size: u32,
fn texture_grow_op(texture_size: u32,
format: ImageFormat,
mode: RenderTargetMode)
-> TextureUpdateOp {
TextureUpdateOp::Grow(old_texture_id,
texture_size,
TextureUpdateOp::Grow(texture_size,
texture_size,
format,
TextureFilter::Linear,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.