Create framebuffers for every texture page

This commit is contained in:
Patrick Walton 2020-03-04 12:35:07 -08:00
parent a3736859ba
commit e50039f4c2
1 changed files with 47 additions and 49 deletions

View File

@ -115,7 +115,7 @@ where
dest_blend_framebuffer: D::Framebuffer, dest_blend_framebuffer: D::Framebuffer,
intermediate_dest_framebuffer: D::Framebuffer, intermediate_dest_framebuffer: D::Framebuffer,
texture_pages: Vec<TexturePage<D>>, texture_pages: Vec<TexturePage<D>>,
render_targets: Vec<RenderTargetInfo<D>>, render_targets: Vec<RenderTargetInfo>,
render_target_stack: Vec<RenderTargetId>, render_target_stack: Vec<RenderTargetId>,
// This is a dummy texture consisting solely of a single `rgba(0, 0, 0, 255)` texel. It serves // This is a dummy texture consisting solely of a single `rgba(0, 0, 0, 255)` texel. It serves
@ -573,43 +573,37 @@ where
fn add_texture_data(&mut self, texture_data: &TextureData) { fn add_texture_data(&mut self, texture_data: &TextureData) {
// Clear out old paint textures. // Clear out old paint textures.
for old_texture_page in self.texture_pages.drain(..) { for old_texture_page in self.texture_pages.drain(..) {
match old_texture_page { let old_texture = self.device.destroy_framebuffer(old_texture_page.framebuffer);
TexturePage::Texture(texture) => self.texture_cache.release_texture(texture), self.texture_cache.release_texture(old_texture);
TexturePage::RenderTarget(_) => {}
}
} }
// Clear out old render targets. // Clear out old render targets.
for render_target in self.render_targets.drain(..) { self.render_targets.clear();
let texture = self.device.destroy_framebuffer(render_target.framebuffer);
self.texture_cache.release_texture(texture);
}
// Build up new paint textures and render targets. // Build up new paint textures and render targets.
for texture_page_data in &texture_data.pages { for texture_page_data in &texture_data.pages {
let texture_size = texture_page_data.size; let texture_size = texture_page_data.size;
let texture_page = self.texture_cache.create_texture(&mut self.device, let texture = self.texture_cache.create_texture(&mut self.device,
TextureFormat::RGBA8, TextureFormat::RGBA8,
texture_size); texture_size);
let texture_page_id = TexturePageId(self.texture_pages.len() as u32);
let must_preserve_contents;
match texture_page_data.contents { match texture_page_data.contents {
TexturePageContents::RenderTarget(render_target_id) => { TexturePageContents::RenderTarget(render_target_id) => {
let framebuffer = self.device.create_framebuffer(texture_page); debug_assert_eq!(render_target_id.0, self.render_targets.len() as u32);
self.render_targets.push(RenderTargetInfo { self.render_targets.push(RenderTargetInfo { texture_page: texture_page_id });
framebuffer, must_preserve_contents = false;
must_preserve_contents: false
});
self.texture_pages.push(TexturePage::RenderTarget(render_target_id));
} }
TexturePageContents::Texels(ref texels) => { TexturePageContents::Texels(ref texels) => {
let texels = color::color_slice_to_u8_slice(texels); let texels = color::color_slice_to_u8_slice(texels);
self.device.upload_to_texture(&texture_page, self.device.upload_to_texture(&texture,
RectI::new(Vector2I::default(), texture_size), RectI::new(Vector2I::default(), texture_size),
TextureDataRef::U8(texels)); TextureDataRef::U8(texels));
must_preserve_contents = true;
self.texture_pages.push(TexturePage::Texture(texture_page));
} }
} }
let framebuffer = self.device.create_framebuffer(texture);
self.texture_pages.push(TexturePage { framebuffer, must_preserve_contents });
} }
} }
@ -1148,7 +1142,8 @@ where
pub fn draw_render_target(&self) -> RenderTarget<D> { pub fn draw_render_target(&self) -> RenderTarget<D> {
match self.render_target_stack.last() { match self.render_target_stack.last() {
Some(&render_target_id) => { Some(&render_target_id) => {
let framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; let texture_page_id = self.render_target_texture_page_id(render_target_id);
let framebuffer = self.texture_page_framebuffer(texture_page_id);
RenderTarget::Framebuffer(framebuffer) RenderTarget::Framebuffer(framebuffer)
} }
None => { None => {
@ -1258,9 +1253,9 @@ where
render_target_id: RenderTargetId, render_target_id: RenderTargetId,
direction: BlurDirection, direction: BlurDirection,
sigma: f32) { sigma: f32) {
let source_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; let src_texture_page = self.render_target_texture_page_id(render_target_id);
let source_texture = self.device.framebuffer_texture(source_framebuffer); let src_texture = self.texture_page(src_texture_page);
let source_texture_size = self.device.texture_size(source_texture); let src_texture_size = self.device.texture_size(src_texture);
let sigma_inv = 1.0 / sigma; let sigma_inv = 1.0 / sigma;
let gauss_coeff_x = SQRT_2_PI_INV * sigma_inv; let gauss_coeff_x = SQRT_2_PI_INV * sigma_inv;
@ -1271,7 +1266,7 @@ where
BlurDirection::X => Vector2F::new(1.0, 0.0), BlurDirection::X => Vector2F::new(1.0, 0.0),
BlurDirection::Y => Vector2F::new(0.0, 1.0), BlurDirection::Y => Vector2F::new(0.0, 1.0),
}; };
let src_offset_scale = src_offset / source_texture_size.to_f32(); let src_offset_scale = src_offset / src_texture_size.to_f32();
let uniforms = vec![ let uniforms = vec![
(&self.tile_filter_blur_program.src_offset_scale_uniform, (&self.tile_filter_blur_program.src_offset_scale_uniform,
@ -1304,8 +1299,8 @@ where
blend_state: Option<BlendState>) { blend_state: Option<BlendState>) {
let clear_color = self.clear_color_for_draw_operation(); let clear_color = self.clear_color_for_draw_operation();
let main_viewport = self.main_viewport(); let main_viewport = self.main_viewport();
let src_framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; let src_texture_page = self.render_target_texture_page_id(render_target_id);
let src_texture = self.device.framebuffer_texture(src_framebuffer); let src_texture = self.texture_page(src_texture_page);
let src_texture_size = self.device.texture_size(src_texture); let src_texture_size = self.device.texture_size(src_texture);
uniforms.extend_from_slice(&[ uniforms.extend_from_slice(&[
@ -1372,8 +1367,9 @@ where
fn clear_color_for_draw_operation(&self) -> Option<ColorF> { fn clear_color_for_draw_operation(&self) -> Option<ColorF> {
let must_preserve_contents = match self.render_target_stack.last() { let must_preserve_contents = match self.render_target_stack.last() {
Some(render_target_id) => { Some(&render_target_id) => {
self.render_targets[render_target_id.0 as usize].must_preserve_contents let texture_page = self.render_target_texture_page_id(render_target_id);
self.texture_pages[texture_page.0 as usize].must_preserve_contents
} }
None => { None => {
self.framebuffer_flags self.framebuffer_flags
@ -1392,8 +1388,9 @@ where
fn preserve_draw_framebuffer(&mut self) { fn preserve_draw_framebuffer(&mut self) {
match self.render_target_stack.last() { match self.render_target_stack.last() {
Some(render_target_id) => { Some(&render_target_id) => {
self.render_targets[render_target_id.0 as usize].must_preserve_contents = true; let texture_page = self.render_target_texture_page_id(render_target_id);
self.texture_pages[texture_page.0 as usize].must_preserve_contents = true;
} }
None => { None => {
self.framebuffer_flags self.framebuffer_flags
@ -1404,9 +1401,9 @@ where
pub fn draw_viewport(&self) -> RectI { pub fn draw_viewport(&self) -> RectI {
match self.render_target_stack.last() { match self.render_target_stack.last() {
Some(render_target_id) => { Some(&render_target_id) => {
let framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer; let texture_page = self.render_target_texture_page_id(render_target_id);
let texture = self.device.framebuffer_texture(framebuffer); let texture = self.texture_page(texture_page);
RectI::new(Vector2I::default(), self.device.texture_size(texture)) RectI::new(Vector2I::default(), self.device.texture_size(texture))
} }
None => self.main_viewport(), None => self.main_viewport(),
@ -1430,14 +1427,16 @@ where
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT)) Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT))
} }
fn render_target_texture_page_id(&self, render_target_id: RenderTargetId) -> TexturePageId {
self.render_targets[render_target_id.0 as usize].texture_page
}
fn texture_page_framebuffer(&self, id: TexturePageId) -> &D::Framebuffer {
&self.texture_pages[id.0 as usize].framebuffer
}
fn texture_page(&self, id: TexturePageId) -> &D::Texture { fn texture_page(&self, id: TexturePageId) -> &D::Texture {
match self.texture_pages[id.0 as usize] { self.device.framebuffer_texture(&self.texture_page_framebuffer(id))
TexturePage::Texture(ref texture) => texture,
TexturePage::RenderTarget(render_target_id) => {
let framebuffer = &self.render_targets[render_target_id.0 as usize].framebuffer;
self.device.framebuffer_texture(framebuffer)
}
}
} }
fn allocate_timer_query(&mut self) -> D::TimerQuery { fn allocate_timer_query(&mut self) -> D::TimerQuery {
@ -1568,16 +1567,15 @@ impl<D> TextureCache<D> where D: Device {
} }
} }
enum TexturePage<D> where D: Device { struct TexturePage<D> where D: Device {
Texture(D::Texture),
RenderTarget(RenderTargetId),
}
struct RenderTargetInfo<D> where D: Device {
framebuffer: D::Framebuffer, framebuffer: D::Framebuffer,
must_preserve_contents: bool, must_preserve_contents: bool,
} }
struct RenderTargetInfo {
texture_page: TexturePageId,
}
trait ToBlendState { trait ToBlendState {
fn to_blend_state(self) -> Option<BlendState>; fn to_blend_state(self) -> Option<BlendState>;
} }