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

Start texture atlases off small, and allow them to grow. #200

Merged
merged 2 commits into from Feb 26, 2016
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Start texture atlases off small, and allow them to grow.

Fixes the Moiré demo in a principled way.
  • Loading branch information
pcwalton committed Feb 26, 2016
commit 3db09bb5135a60f52ae388d95d7fe47048b923b8
@@ -1117,24 +1117,8 @@ impl Device {
RenderTargetMode::RenderTarget => {
self.bind_color_texture(texture_id);
self.set_texture_parameters(filter);

self.upload_2d_texture_image(width, height, internal_format, gl_format, None);

let fbo_ids: Vec<_> =
gl::gen_framebuffers(1).into_iter().map(|fbo_id| FBOId(fbo_id)).collect();
for fbo_id in &fbo_ids[..] {
gl::bind_framebuffer(gl::FRAMEBUFFER, fbo_id.0);

gl::framebuffer_texture_2d(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
texture_id.0,
0);
}

gl::bind_framebuffer(gl::FRAMEBUFFER, self.default_fbo);

self.textures.get_mut(&texture_id).unwrap().fbo_ids = fbo_ids;
self.create_fbo_for_texture_if_necessary(texture_id);
}
RenderTargetMode::None => {
texture_id.bind();
@@ -1148,7 +1132,63 @@ impl Device {
}
}

#[allow(dead_code)]
pub fn create_fbo_for_texture_if_necessary(&mut self, texture_id: TextureId) {
if !self.textures.get(&texture_id).unwrap().fbo_ids.is_empty() {
return
}

let fbo_ids: Vec<_> =
gl::gen_framebuffers(1).into_iter().map(|fbo_id| FBOId(fbo_id)).collect();
for fbo_id in &fbo_ids[..] {
gl::bind_framebuffer(gl::FRAMEBUFFER, fbo_id.0);

gl::framebuffer_texture_2d(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
texture_id.0,
0);
}

gl::bind_framebuffer(gl::FRAMEBUFFER, self.default_fbo);

self.textures.get_mut(&texture_id).unwrap().fbo_ids = fbo_ids;
}

pub fn resize_texture(&mut self,
new_texture_id: TextureId,
old_texture_id: TextureId,
width: u32,
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);

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 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(None);
self.deinit_texture(old_texture_id);
}

pub fn deinit_texture(&mut self, texture_id: TextureId) {
debug_assert!(self.inside_frame);

@@ -97,4 +97,72 @@ impl<T: FreeListItem> FreeList<T> {
item.set_next_free_id(self.first_free_index);
self.first_free_index = Some(id);
}

/// NB: This iterates over free items too!

This comment has been minimized.

@glennw

glennw Feb 26, 2016

Member

I'm uneasy about this since it exposes internal details - is there a way to avoid it?

This comment has been minimized.

@pcwalton

pcwalton Feb 26, 2016

Author Collaborator

Maybe I can yield indices instead—let me see.

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 struct IterMut<'a, T> where T: FreeListItem + 'a {
free_list: &'a mut FreeList<T>,
next_index: Option<FreeListItemId>,
next_free_index: Option<FreeListItemId>,
}

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
}
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,6 +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),
}

pub struct TextureUpdate {
@@ -504,6 +504,20 @@ impl Renderer {
}
}
}
TextureUpdateOp::Grow(old_texture_id,
new_width,
new_height,
format,
filter,
mode) => {
self.device.resize_texture(update.id,
old_texture_id,
new_width,
new_height,
format,
filter,
mode);
}
TextureUpdateOp::Update(x, y, width, height, details) => {
match details {
TextureUpdateDetails::Raw => {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.