1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 extern crate gleam;
6 extern crate glutin;
7 extern crate webrender;
8 extern crate winit;
9 
10 #[path = "common/boilerplate.rs"]
11 mod boilerplate;
12 
13 use crate::boilerplate::{Example, HandyDandyRectBuilder};
14 use gleam::gl;
15 use std::mem;
16 use webrender::api::*;
17 use webrender::render_api::*;
18 use webrender::api::units::*;
19 
20 
21 struct ImageGenerator {
22     patterns: [[u8; 3]; 6],
23     next_pattern: usize,
24     current_image: Vec<u8>,
25 }
26 
27 impl ImageGenerator {
new() -> Self28     fn new() -> Self {
29         ImageGenerator {
30             next_pattern: 0,
31             patterns: [
32                 [1, 0, 0],
33                 [0, 1, 0],
34                 [0, 0, 1],
35                 [1, 1, 0],
36                 [0, 1, 1],
37                 [1, 0, 1],
38             ],
39             current_image: Vec::new(),
40         }
41     }
42 
generate_image(&mut self, size: i32)43     fn generate_image(&mut self, size: i32) {
44         let pattern = &self.patterns[self.next_pattern];
45         self.current_image.clear();
46         for y in 0 .. size {
47             for x in 0 .. size {
48                 let lum = 255 * (1 - (((x & 8) == 0) ^ ((y & 8) == 0)) as u8);
49                 self.current_image.extend_from_slice(&[
50                     lum * pattern[0],
51                     lum * pattern[1],
52                     lum * pattern[2],
53                     0xff,
54                 ]);
55             }
56         }
57 
58         self.next_pattern = (self.next_pattern + 1) % self.patterns.len();
59     }
60 
take(&mut self) -> Vec<u8>61     fn take(&mut self) -> Vec<u8> {
62         mem::replace(&mut self.current_image, Vec::new())
63     }
64 }
65 
66 impl ExternalImageHandler for ImageGenerator {
lock( &mut self, _key: ExternalImageId, channel_index: u8, _rendering: ImageRendering ) -> ExternalImage67     fn lock(
68         &mut self,
69         _key: ExternalImageId,
70         channel_index: u8,
71         _rendering: ImageRendering
72     ) -> ExternalImage {
73         self.generate_image(channel_index as i32);
74         ExternalImage {
75             uv: TexelRect::new(0.0, 0.0, 1.0, 1.0),
76             source: ExternalImageSource::RawData(&self.current_image),
77         }
78     }
unlock(&mut self, _key: ExternalImageId, _channel_index: u8)79     fn unlock(&mut self, _key: ExternalImageId, _channel_index: u8) {}
80 }
81 
82 struct App {
83     stress_keys: Vec<ImageKey>,
84     image_key: Option<ImageKey>,
85     image_generator: ImageGenerator,
86     swap_keys: Vec<ImageKey>,
87     swap_index: usize,
88 }
89 
90 impl Example for App {
render( &mut self, api: &mut RenderApi, builder: &mut DisplayListBuilder, txn: &mut Transaction, _device_size: DeviceIntSize, pipeline_id: PipelineId, _document_id: DocumentId, )91     fn render(
92         &mut self,
93         api: &mut RenderApi,
94         builder: &mut DisplayListBuilder,
95         txn: &mut Transaction,
96         _device_size: DeviceIntSize,
97         pipeline_id: PipelineId,
98         _document_id: DocumentId,
99     ) {
100         let bounds = (0, 0).to(512, 512);
101         let space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
102 
103         builder.push_simple_stacking_context(
104             bounds.min,
105             space_and_clip.spatial_id,
106             PrimitiveFlags::IS_BACKFACE_VISIBLE,
107         );
108 
109         let x0 = 50.0;
110         let y0 = 50.0;
111         let image_size = LayoutSize::new(4.0, 4.0);
112 
113         if self.swap_keys.is_empty() {
114             let key0 = api.generate_image_key();
115             let key1 = api.generate_image_key();
116 
117             self.image_generator.generate_image(128);
118             txn.add_image(
119                 key0,
120                 ImageDescriptor::new(128, 128, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE),
121                 ImageData::new(self.image_generator.take()),
122                 None,
123             );
124 
125             self.image_generator.generate_image(128);
126             txn.add_image(
127                 key1,
128                 ImageDescriptor::new(128, 128, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE),
129                 ImageData::new(self.image_generator.take()),
130                 None,
131             );
132 
133             self.swap_keys.push(key0);
134             self.swap_keys.push(key1);
135         }
136 
137         for (i, key) in self.stress_keys.iter().enumerate() {
138             let x = (i % 128) as f32;
139             let y = (i / 128) as f32;
140             let info = CommonItemProperties::new(
141                 LayoutRect::from_origin_and_size(
142                     LayoutPoint::new(x0 + image_size.width * x, y0 + image_size.height * y),
143                     image_size,
144                 ),
145                 space_and_clip,
146             );
147 
148             builder.push_image(
149                 &info,
150                 bounds,
151                 ImageRendering::Auto,
152                 AlphaType::PremultipliedAlpha,
153                 *key,
154                 ColorF::WHITE,
155             );
156         }
157 
158         if let Some(image_key) = self.image_key {
159             let image_size = LayoutSize::new(100.0, 100.0);
160             let info = CommonItemProperties::new(
161                 LayoutRect::from_origin_and_size(LayoutPoint::new(100.0, 100.0), image_size),
162                 space_and_clip,
163             );
164             builder.push_image(
165                 &info,
166                 bounds,
167                 ImageRendering::Auto,
168                 AlphaType::PremultipliedAlpha,
169                 image_key,
170                 ColorF::WHITE,
171             );
172         }
173 
174         let swap_key = self.swap_keys[self.swap_index];
175         let image_size = LayoutSize::new(64.0, 64.0);
176         let info = CommonItemProperties::new(
177             LayoutRect::from_origin_and_size(LayoutPoint::new(100.0, 400.0), image_size),
178             space_and_clip,
179         );
180         builder.push_image(
181             &info,
182             bounds,
183             ImageRendering::Auto,
184             AlphaType::PremultipliedAlpha,
185             swap_key,
186             ColorF::WHITE,
187         );
188         self.swap_index = 1 - self.swap_index;
189 
190         builder.pop_stacking_context();
191     }
192 
on_event( &mut self, event: winit::WindowEvent, api: &mut RenderApi, document_id: DocumentId, ) -> bool193     fn on_event(
194         &mut self,
195         event: winit::WindowEvent,
196         api: &mut RenderApi,
197         document_id: DocumentId,
198     ) -> bool {
199         match event {
200             winit::WindowEvent::KeyboardInput {
201                 input: winit::KeyboardInput {
202                     state: winit::ElementState::Pressed,
203                     virtual_keycode: Some(key),
204                     ..
205                 },
206                 ..
207             } => {
208                 let mut txn = Transaction::new();
209 
210                 match key {
211                     winit::VirtualKeyCode::S => {
212                         self.stress_keys.clear();
213 
214                         for _ in 0 .. 16 {
215                             for _ in 0 .. 16 {
216                                 let size = 4;
217 
218                                 let image_key = api.generate_image_key();
219 
220                                 self.image_generator.generate_image(size);
221 
222                                 txn.add_image(
223                                     image_key,
224                                     ImageDescriptor::new(
225                                         size,
226                                         size,
227                                         ImageFormat::BGRA8,
228                                         ImageDescriptorFlags::IS_OPAQUE,
229                                     ),
230                                     ImageData::new(self.image_generator.take()),
231                                     None,
232                                 );
233 
234                                 self.stress_keys.push(image_key);
235                             }
236                         }
237                     }
238                     winit::VirtualKeyCode::D => if let Some(image_key) = self.image_key.take() {
239                         txn.delete_image(image_key);
240                     },
241                     winit::VirtualKeyCode::U => if let Some(image_key) = self.image_key {
242                         let size = 128;
243                         self.image_generator.generate_image(size);
244 
245                         txn.update_image(
246                             image_key,
247                             ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE),
248                             ImageData::new(self.image_generator.take()),
249                             &DirtyRect::All,
250                         );
251                     },
252                     winit::VirtualKeyCode::E => {
253                         if let Some(image_key) = self.image_key.take() {
254                             txn.delete_image(image_key);
255                         }
256 
257                         let size = 32;
258                         let image_key = api.generate_image_key();
259 
260                         let image_data = ExternalImageData {
261                             id: ExternalImageId(0),
262                             channel_index: size as u8,
263                             image_type: ExternalImageType::Buffer,
264                         };
265 
266                         txn.add_image(
267                             image_key,
268                             ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE),
269                             ImageData::External(image_data),
270                             None,
271                         );
272 
273                         self.image_key = Some(image_key);
274                     }
275                     winit::VirtualKeyCode::R => {
276                         if let Some(image_key) = self.image_key.take() {
277                             txn.delete_image(image_key);
278                         }
279 
280                         let image_key = api.generate_image_key();
281                         let size = 32;
282                         self.image_generator.generate_image(size);
283 
284                         txn.add_image(
285                             image_key,
286                             ImageDescriptor::new(size, size, ImageFormat::BGRA8, ImageDescriptorFlags::IS_OPAQUE),
287                             ImageData::new(self.image_generator.take()),
288                             None,
289                         );
290 
291                         self.image_key = Some(image_key);
292                     }
293                     _ => {}
294                 }
295 
296                 api.send_transaction(document_id, txn);
297                 return true;
298             }
299             _ => {}
300         }
301 
302         false
303     }
304 
get_image_handler( &mut self, _gl: &dyn gl::Gl, ) -> Option<Box<dyn ExternalImageHandler>>305     fn get_image_handler(
306         &mut self,
307         _gl: &dyn gl::Gl,
308     ) -> Option<Box<dyn ExternalImageHandler>> {
309         Some(Box::new(ImageGenerator::new()))
310     }
311 }
312 
main()313 fn main() {
314     let mut app = App {
315         image_key: None,
316         stress_keys: Vec::new(),
317         image_generator: ImageGenerator::new(),
318         swap_keys: Vec::new(),
319         swap_index: 0,
320     };
321     boilerplate::main_wrapper(&mut app, None);
322 }
323