ltk/gles_render/
surface_cache.rsuse glow::HasContext;
use crate::types::Rect;
use super::GlesCanvas;
use super::helpers::{ alloc_fbo_tex, ortho_rect };
pub( crate ) struct OffscreenTarget
{
fbo: glow::Framebuffer,
saved_fbo: glow::Framebuffer,
saved_tex: glow::Texture,
saved_size: ( u32, u32 ),
saved_clip: Option<Rect>,
saved_alpha: f32,
saved_layer: bool,
}
impl GlesCanvas
{
pub( crate ) fn cached_surface( &self, key: u64 ) -> Option<( glow::Texture, u32, u32 )>
{
self.image_cache.borrow_mut().surface( key )
}
pub( crate ) fn insert_cached_surface( &self, key: u64, tex: glow::Texture, w: u32, h: u32 )
{
self.image_cache.borrow_mut().insert_surface( &self.gl, key, tex, w, h );
}
pub( crate ) fn begin_offscreen( &mut self, w: u32, h: u32 ) -> OffscreenTarget
{
self.flush_clip_layer();
let ( fbo, tex ) = unsafe
{
let fbo = self.gl.create_framebuffer().expect( "create_framebuffer" );
let tex = alloc_fbo_tex( &self.gl, self.version, w, h );
self.gl.bind_framebuffer( glow::FRAMEBUFFER, Some( fbo ) );
self.gl.framebuffer_texture_2d( glow::FRAMEBUFFER, glow::COLOR_ATTACHMENT0, glow::TEXTURE_2D, Some( tex ), 0 );
( fbo, tex )
};
let target = OffscreenTarget
{
fbo,
saved_fbo: self.fbo,
saved_tex: self.fbo_tex,
saved_size: ( self.width, self.height ),
saved_clip: self.clip_scissor,
saved_alpha: self.global_alpha,
saved_layer: self.clip_layer_active,
};
self.fbo = fbo;
self.fbo_tex = tex;
self.width = w;
self.height = h;
self.clip_scissor = None;
self.global_alpha = 1.0;
self.clip_layer_active = false;
self.clear();
target
}
pub( crate ) fn end_offscreen( &mut self, target: OffscreenTarget ) -> glow::Texture
{
let tex = self.fbo_tex;
self.fbo = target.saved_fbo;
self.fbo_tex = target.saved_tex;
self.width = target.saved_size.0;
self.height = target.saved_size.1;
self.clip_scissor = target.saved_clip;
self.global_alpha = target.saved_alpha;
self.clip_layer_active = target.saved_layer;
unsafe { self.gl.delete_framebuffer( target.fbo ); }
self.activate_target();
tex
}
pub( crate ) fn blit_texture( &mut self, tex: glow::Texture, w: u32, h: u32, x: f32, y: f32 )
{
let dest = Rect { x, y, width: w as f32, height: h as f32 };
if let Some( clip ) = self.clip_scissor
{
let outside = dest.x >= clip.x + clip.width || dest.x + dest.width <= clip.x
|| dest.y >= clip.y + clip.height || dest.y + dest.height <= clip.y;
if outside { return; }
}
self.activate_target();
let mvp = ortho_rect( self.width, self.height, dest );
let alpha = self.global_alpha;
unsafe
{
self.gl.use_program( Some( self.sub_blit_program ) );
self.gl.uniform_matrix_4_f32_slice( Some( &self.u_subblit_mvp ), false, &mvp );
self.gl.uniform_1_f32( Some( &self.u_subblit_opacity ), alpha );
self.gl.uniform_1_f32( Some( &self.u_subblit_fade_bottom ), 0.0 );
self.gl.uniform_1_f32( Some( &self.u_subblit_height_px ), h as f32 );
self.gl.active_texture( glow::TEXTURE0 );
self.gl.bind_texture( glow::TEXTURE_2D, Some( tex ) );
self.gl.uniform_1_i32( Some( &self.u_subblit_sampler ), 0 );
self.gl.bind_vertex_array( Some( self.quad_vao ) );
self.gl.draw_arrays( glow::TRIANGLES, 0, 6 );
self.gl.bind_vertex_array( None );
self.gl.bind_texture( glow::TEXTURE_2D, None );
}
}
}