aboutsummaryrefslogtreecommitdiffstats
path: root/third_party/webrender/examples/blob.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webrender/examples/blob.rs')
-rw-r--r--third_party/webrender/examples/blob.rs290
1 files changed, 0 insertions, 290 deletions
diff --git a/third_party/webrender/examples/blob.rs b/third_party/webrender/examples/blob.rs
deleted file mode 100644
index 65c048c87be..00000000000
--- a/third_party/webrender/examples/blob.rs
+++ /dev/null
@@ -1,290 +0,0 @@
-/* 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 rayon;
-extern crate webrender;
-extern crate winit;
-
-#[path = "common/boilerplate.rs"]
-mod boilerplate;
-
-use crate::boilerplate::{Example, HandyDandyRectBuilder};
-use rayon::{ThreadPool, ThreadPoolBuilder};
-use rayon::prelude::*;
-use std::collections::HashMap;
-use std::sync::Arc;
-use webrender::api::{self, DisplayListBuilder, DocumentId, PipelineId, PrimitiveFlags};
-use webrender::api::{ColorF, CommonItemProperties, SpaceAndClipInfo, ImageDescriptorFlags};
-use webrender::api::units::*;
-use webrender::render_api::*;
-use webrender::euclid::size2;
-
-// This example shows how to implement a very basic BlobImageHandler that can only render
-// a checkerboard pattern.
-
-// The deserialized command list internally used by this example is just a color.
-type ImageRenderingCommands = api::ColorU;
-
-// Serialize/deserialize the blob.
-// For real usecases you should probably use serde rather than doing it by hand.
-
-fn serialize_blob(color: api::ColorU) -> Arc<Vec<u8>> {
- Arc::new(vec![color.r, color.g, color.b, color.a])
-}
-
-fn deserialize_blob(blob: &[u8]) -> Result<ImageRenderingCommands, ()> {
- let mut iter = blob.iter();
- return match (iter.next(), iter.next(), iter.next(), iter.next()) {
- (Some(&r), Some(&g), Some(&b), Some(&a)) => Ok(api::ColorU::new(r, g, b, a)),
- (Some(&a), None, None, None) => Ok(api::ColorU::new(a, a, a, a)),
- _ => Err(()),
- };
-}
-
-// This is the function that applies the deserialized drawing commands and generates
-// actual image data.
-fn render_blob(
- commands: Arc<ImageRenderingCommands>,
- descriptor: &api::BlobImageDescriptor,
- tile: TileOffset,
-) -> api::BlobImageResult {
- let color = *commands;
-
- // Note: This implementation ignores the dirty rect which isn't incorrect
- // but is a missed optimization.
-
- // Allocate storage for the result. Right now the resource cache expects the
- // tiles to have have no stride or offset.
- let bpp = 4;
- let mut texels = Vec::with_capacity((descriptor.rect.size.area() * bpp) as usize);
-
- // Generate a per-tile pattern to see it in the demo. For a real use case it would not
- // make sense for the rendered content to depend on its tile.
- let tile_checker = (tile.x % 2 == 0) != (tile.y % 2 == 0);
-
- let [w, h] = descriptor.rect.size.to_array();
- let offset = descriptor.rect.origin;
-
- for y in 0..h {
- for x in 0..w {
- // Apply the tile's offset. This is important: all drawing commands should be
- // translated by this offset to give correct results with tiled blob images.
- let x2 = x + offset.x;
- let y2 = y + offset.y;
-
- // Render a simple checkerboard pattern
- let checker = if (x2 % 20 >= 10) != (y2 % 20 >= 10) {
- 1
- } else {
- 0
- };
- // ..nested in the per-tile checkerboard pattern
- let tc = if tile_checker { 0 } else { (1 - checker) * 40 };
-
- match descriptor.format {
- api::ImageFormat::BGRA8 => {
- texels.push(color.b * checker + tc);
- texels.push(color.g * checker + tc);
- texels.push(color.r * checker + tc);
- texels.push(color.a * checker + tc);
- }
- api::ImageFormat::R8 => {
- texels.push(color.a * checker + tc);
- }
- _ => {
- return Err(api::BlobImageError::Other(
- format!("Unsupported image format"),
- ));
- }
- }
- }
- }
-
- Ok(api::RasterizedBlobImage {
- data: Arc::new(texels),
- rasterized_rect: size2(w, h).into(),
- })
-}
-
-struct CheckerboardRenderer {
- // We are going to defer the rendering work to worker threads.
- // Using a pre-built Arc<ThreadPool> rather than creating our own threads
- // makes it possible to share the same thread pool as the glyph renderer (if we
- // want to).
- workers: Arc<ThreadPool>,
-
- // The deserialized drawing commands.
- // In this example we store them in Arcs. This isn't necessary since in this simplified
- // case the command list is a simple 32 bits value and would be cheap to clone before sending
- // to the workers. But in a more realistic scenario the commands would typically be bigger
- // and more expensive to clone, so let's pretend it is also the case here.
- image_cmds: HashMap<api::BlobImageKey, Arc<ImageRenderingCommands>>,
-}
-
-impl CheckerboardRenderer {
- fn new(workers: Arc<ThreadPool>) -> Self {
- CheckerboardRenderer {
- image_cmds: HashMap::new(),
- workers,
- }
- }
-}
-
-impl api::BlobImageHandler for CheckerboardRenderer {
- fn create_similar(&self) -> Box<dyn api::BlobImageHandler> {
- Box::new(CheckerboardRenderer::new(Arc::clone(&self.workers)))
- }
-
- fn add(&mut self, key: api::BlobImageKey, cmds: Arc<api::BlobImageData>,
- _visible_rect: &DeviceIntRect, _: api::TileSize) {
- self.image_cmds
- .insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
- }
-
- fn update(&mut self, key: api::BlobImageKey, cmds: Arc<api::BlobImageData>,
- _visible_rect: &DeviceIntRect, _dirty_rect: &BlobDirtyRect) {
- // Here, updating is just replacing the current version of the commands with
- // the new one (no incremental updates).
- self.image_cmds
- .insert(key, Arc::new(deserialize_blob(&cmds[..]).unwrap()));
- }
-
- fn delete(&mut self, key: api::BlobImageKey) {
- self.image_cmds.remove(&key);
- }
-
- fn prepare_resources(
- &mut self,
- _services: &dyn api::BlobImageResources,
- _requests: &[api::BlobImageParams],
- ) {}
-
- fn enable_multithreading(&mut self, _: bool) {}
- fn delete_font(&mut self, _font: api::FontKey) {}
- fn delete_font_instance(&mut self, _instance: api::FontInstanceKey) {}
- fn clear_namespace(&mut self, _namespace: api::IdNamespace) {}
- fn create_blob_rasterizer(&mut self) -> Box<dyn api::AsyncBlobImageRasterizer> {
- Box::new(Rasterizer {
- workers: Arc::clone(&self.workers),
- image_cmds: self.image_cmds.clone(),
- })
- }
-}
-
-struct Rasterizer {
- workers: Arc<ThreadPool>,
- image_cmds: HashMap<api::BlobImageKey, Arc<ImageRenderingCommands>>,
-}
-
-impl api::AsyncBlobImageRasterizer for Rasterizer {
- fn rasterize(
- &mut self,
- requests: &[api::BlobImageParams],
- _low_priority: bool
- ) -> Vec<(api::BlobImageRequest, api::BlobImageResult)> {
- let requests: Vec<(&api::BlobImageParams, Arc<ImageRenderingCommands>)> = requests.into_iter().map(|params| {
- (params, Arc::clone(&self.image_cmds[&params.request.key]))
- }).collect();
-
- self.workers.install(|| {
- requests.into_par_iter().map(|(params, commands)| {
- (params.request, render_blob(commands, &params.descriptor, params.request.tile))
- }).collect()
- })
- }
-}
-
-struct App {}
-
-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 space_and_clip = SpaceAndClipInfo::root_scroll(pipeline_id);
-
- builder.push_simple_stacking_context(
- LayoutPoint::zero(),
- space_and_clip.spatial_id,
- PrimitiveFlags::IS_BACKFACE_VISIBLE,
- );
-
- let size1 = DeviceIntSize::new(500, 500);
- let blob_img1 = api.generate_blob_image_key();
- txn.add_blob_image(
- blob_img1,
- api::ImageDescriptor::new(
- size1.width,
- size1.height,
- api::ImageFormat::BGRA8,
- ImageDescriptorFlags::IS_OPAQUE,
- ),
- serialize_blob(api::ColorU::new(50, 50, 150, 255)),
- size1.into(),
- Some(128),
- );
- let bounds = (30, 30).by(size1.width, size1.height);
- builder.push_image(
- &CommonItemProperties::new(bounds, space_and_clip),
- bounds,
- api::ImageRendering::Auto,
- api::AlphaType::PremultipliedAlpha,
- blob_img1.as_image(),
- ColorF::WHITE,
- );
-
- let size2 = DeviceIntSize::new(256, 256);
- let blob_img2 = api.generate_blob_image_key();
- txn.add_blob_image(
- blob_img2,
- api::ImageDescriptor::new(
- size2.width,
- size2.height,
- api::ImageFormat::BGRA8,
- ImageDescriptorFlags::IS_OPAQUE,
- ),
- serialize_blob(api::ColorU::new(50, 150, 50, 255)),
- size2.into(),
- None,
- );
- let bounds = (600, 600).by(size2.width, size2.height);
- builder.push_image(
- &CommonItemProperties::new(bounds, space_and_clip),
- bounds,
- api::ImageRendering::Auto,
- api::AlphaType::PremultipliedAlpha,
- blob_img2.as_image(),
- ColorF::WHITE,
- );
-
- builder.pop_stacking_context();
- }
-}
-
-fn main() {
- let workers =
- ThreadPoolBuilder::new().thread_name(|idx| format!("WebRender:Worker#{}", idx))
- .build();
-
- let workers = Arc::new(workers.unwrap());
-
- let opts = webrender::RendererOptions {
- workers: Some(Arc::clone(&workers)),
- // Register our blob renderer, so that WebRender integrates it in the resource cache..
- // Share the same pool of worker threads between WebRender and our blob renderer.
- blob_image_handler: Some(Box::new(CheckerboardRenderer::new(Arc::clone(&workers)))),
- ..Default::default()
- };
-
- let mut app = App {};
-
- boilerplate::main_wrapper(&mut app, Some(opts));
-}