/* 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<u8>,
}
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 ],
0 xff,
]);
}
}
self .next_pattern = (
self .next_pattern +
1 ) %
self .patterns.len();
}
fn take(&
mut self ) -> Vec<u8> {
mem::replace(&
mut self .current_image, Vec::new())
}
}
impl ExternalImageHandler
for ImageGenerator {
fn lock(
&
mut self ,
_key: ExternalImageId,
channel_index: u8,
_is_composited: bool,
) -> 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<ImageKey>,
image_key: Option<ImageKey>,
image_generator: ImageGenerator,
swap_keys: Vec<ImageKey>,
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(
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 {
event: winit::event::KeyEvent {
state: winit::event::ElementState::Pressed,
ref logical_key,
..
},
..
} => {
use winit::keyboard::Key;
let mut txn = Transaction::new();
match logical_key.as_ref() {
Key::Character("s" ) | Key::Character("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);
}
}
}
Key::Character("d" ) | Key::Character("D" ) => if let Some(image_key) = self .image_key.take() {
txn.delete_image(image_key);
},
Key::Character("u" ) | Key::Character("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,
);
},
Key::Character("e" ) | Key::Character("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,
normalized_uvs: false ,
};
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);
}
Key::Character("r" ) | Key::Character("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<Box <dyn ExternalImageHandler>> {
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);
}
Messung V0.5 in Prozent C=74 H=95 G=84
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-08-25)
¤
*© Formatika GbR, Deutschland