/* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ extern crate gleam; extern crate glutin; extern crate webrender; extern crate winit; #[path = "common/boilerplate.rs"] mod boilerplate; use crate::boilerplate::{Example, HandyDandyRectBuilder}; use gleam::gl; use std::mem; use webrender::api::*; use webrender::render_api::*; use webrender::api::units::*; struct ImageGenerator { patterns: [[u8; 3]; 6], next_pattern: usize, current_image: Vec, } impl ImageGenerator { fn new() -> Self { ImageGenerator { next_pattern: 0, patterns: [ [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 0], [0, 1, 1], [1, 0, 1], ], current_image: Vec::new(), } } fn generate_image(&mut self, size: i32) { let pattern = &self.patterns[self.next_pattern]; self.current_image.clear(); for y in 0 .. size { for x in 0 .. size { let lum = 255 * (1 - (((x & 8) == 0) ^ ((y & 8) == 0)) as u8); self.current_image.extend_from_slice(&[ lum * pattern[0], lum * pattern[1], lum * pattern[2], 0xff, ]); } } self.next_pattern = (self.next_pattern + 1) % self.patterns.len(); } fn take(&mut self) -> Vec { mem::replace(&mut self.current_image, Vec::new()) } } impl ExternalImageHandler for ImageGenerator { fn lock( &mut self, _key: ExternalImageId, channel_index: u8, ) -> ExternalImage { self.generate_image(channel_index as i32); ExternalImage { uv: TexelRect::new(0.0, 0.0, 1.0, 1.0), source: ExternalImageSource::RawData(&self.current_image), } } fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) {} } struct App { stress_keys: Vec, image_key: Option, image_generator: ImageGenerator, swap_keys: Vec, swap_index: usize, } impl Example for App { fn render( &mut self, api: &mut RenderApi, builder: &mut DisplayListBuilder, txn: &mut Transaction, _device_size: DeviceIntSize, pipeline_id: PipelineId, _document_id: DocumentId, ) { let bounds = (0, 0).to(512, 512); let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id); builder.push_simple_stacking_context( bounds.min, space_and_clip.spatial_id, PrimitiveFlags::IS_BACKFACE_VISIBLE, ); let x0 = 50.0; let y0 = 50.0; let image_size = LayoutSize::new(4.0, 4.0); if self.swap_keys.is_empty() { let key0 = api.generate_image_key(); let key1 = api.generate_image_key(); self.image_generator.generate_image(128); txn.add_image( key0, ImageDescriptor::new(128, 128, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), ImageData::new(self.image_generator.take()), None, ); self.image_generator.generate_image(128); txn.add_image( key1, ImageDescriptor::new(128, 128, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), ImageData::new(self.image_generator.take()), None, ); self.swap_keys.push(key0); self.swap_keys.push(key1); } for (i, key) in self.stress_keys.iter().enumerate() { let x = (i % 128) as f32; let y = (i / 128) as f32; let info = CommonItemProperties::new( LayoutRect::from_origin_and_size( LayoutPoint::new(x0 + image_size.width * x, y0 + image_size.height * y), image_size, ), space_and_clip, ); builder.push_image( &info, bounds, ImageRendering::Auto, AlphaType::PremultipliedAlpha, *key, ColorF::WHITE, ); } if let Some(image_key) = self.image_key { let image_size = LayoutSize::new(100.0, 100.0); let info = CommonItemProperties::new( LayoutRect::from_origin_and_size(LayoutPoint::new(100.0, 100.0), image_size), space_and_clip, ); builder.push_image( &info, bounds, ImageRendering::Auto, AlphaType::PremultipliedAlpha, image_key, ColorF::WHITE, ); } let swap_key = self.swap_keys[self.swap_index]; let image_size = LayoutSize::new(64.0, 64.0); let info = CommonItemProperties::new( LayoutRect::from_origin_and_size(LayoutPoint::new(100.0, 400.0), image_size), space_and_clip, ); builder.push_image( &info, bounds, ImageRendering::Auto, AlphaType::PremultipliedAlpha, swap_key, ColorF::WHITE, ); self.swap_index = 1 - self.swap_index; builder.pop_stacking_context(); } fn on_event( &mut self, event: winit::event::WindowEvent, _window: &winit::window::Window, api: &mut RenderApi, document_id: DocumentId, ) -> bool { match event { winit::event::WindowEvent::KeyboardInput { input: winit::event::KeyboardInput { state: winit::event::ElementState::Pressed, virtual_keycode: Some(key), .. }, .. } => { let mut txn = Transaction::new(); match key { winit::event::VirtualKeyCode::S => { self.stress_keys.clear(); for _ in 0 .. 16 { for _ in 0 .. 16 { let size = 4; let image_key = api.generate_image_key(); self.image_generator.generate_image(size); txn.add_image( image_key, ImageDescriptor::new( size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE, ), ImageData::new(self.image_generator.take()), None, ); self.stress_keys.push(image_key); } } } winit::event::VirtualKeyCode::D => if let Some(image_key) = self.image_key.take() { txn.delete_image(image_key); }, winit::event::VirtualKeyCode::U => if let Some(image_key) = self.image_key { let size = 128; self.image_generator.generate_image(size); txn.update_image( image_key, ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), ImageData::new(self.image_generator.take()), &DirtyRect::All, ); }, winit::event::VirtualKeyCode::E => { if let Some(image_key) = self.image_key.take() { txn.delete_image(image_key); } let size = 32; let image_key = api.generate_image_key(); let image_data = ExternalImageData { id: ExternalImageId(0), channel_index: size as u8, image_type: ExternalImageType::Buffer, }; txn.add_image( image_key, ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), ImageData::External(image_data), None, ); self.image_key = Some(image_key); } winit::event::VirtualKeyCode::R => { if let Some(image_key) = self.image_key.take() { txn.delete_image(image_key); } let image_key = api.generate_image_key(); let size = 32; self.image_generator.generate_image(size); txn.add_image( image_key, ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE), ImageData::new(self.image_generator.take()), None, ); self.image_key = Some(image_key); } _ => {} } api.send_transaction(document_id, txn); return true; } _ => {} } false } fn get_image_handler( &mut self, _gl: &dyn gl::Gl, ) -> Option> { Some(Box::new(ImageGenerator::new())) } } fn main() { let mut app = App { image_key: None, stress_keys: Vec::new(), image_generator: ImageGenerator::new(), swap_keys: Vec::new(), swap_index: 0, }; boilerplate::main_wrapper(&mut app, None); }