Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/wr/examples/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 12 kB image not shown  

Quelle  multiwindow.rs

  Sprache: Rust
 

/* 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 euclid;
extern crate gleam;
extern crate glutin;
extern crate webrender;
extern crate winit;

use gleam::gl;
use glutin::config::{ConfigTemplateBuilder, GlConfig};
use glutin::context::{
    ContextApi, ContextAttributesBuilder, NotCurrentGlContext,
    PossiblyCurrentContext, Version,
};
use glutin::display::{GetGlDisplay, GlDisplay};
use glutin::surface::{GlSurface, Surface, SurfaceAttributesBuilder, WindowSurface};
use glutin_winit::DisplayBuilder;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::num::NonZeroU32;
use std::rc::Rc;
use webrender::api::*;
use webrender::api::units::*;
use webrender::render_api::*;
use webrender::DebugFlags;
use winit::application::ApplicationHandler;
use winit::dpi::LogicalSize;
use winit::event::{ElementState, KeyEvent, WindowEvent};
use winit::event_loop::{ActiveEventLoop, EventLoop};
use winit::keyboard::{Key, NamedKey};
use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle};

struct Notifier {
    events_proxy: winit::event_loop::EventLoopProxy<()>,
}

impl Notifier {
    fn new(events_proxy: winit::event_loop::EventLoopProxy<()>) -> Notifier {
        Notifier { events_proxy }
    }
}

impl RenderNotifier for Notifier {
    fn clone(&self) -> Box<dyn RenderNotifier> {
        Box::new(Notifier {
            events_proxy: self.events_proxy.clone(),
        })
    }

    fn wake_up(&self, _composite_needed: bool) {
        #[cfg(not(target_os = "android"))]
        let _ = self.events_proxy.send_event(());
    }

    fn new_frame_ready(&self,
                       _: DocumentId,
                       _: FramePublishId,
                       params: &FrameReadyParams) {
        self.wake_up(params.render);
    }
}

struct Window {
    window: winit::window::Window,
    gl_surface: Surface<WindowSurface>,
    gl_context: PossiblyCurrentContext,
    renderer: webrender::Renderer,
    name: &'static str,
    pipeline_id: PipelineId,
    document_id: DocumentId,
    epoch: Epoch,
    api: RenderApi,
    font_instance_key: FontInstanceKey,
}

fn load_gl_fns(is_gles: bool, gl_display: &impl GlDisplay) -> Rc<dyn gl::Gl> {
    if is_gles {
        unsafe {
            gl::GlesFns::load_with(|symbol| {
                gl_display.get_proc_address(&CString::new(symbol).unwrap()) as *const _
            })
        }
    } else {
        unsafe {
            gl::GlFns::load_with(|symbol| {
                gl_display.get_proc_address(&CString::new(symbol).unwrap()) as *const _
            })
        }
    }
}

impl Window {
    fn new(
        name: &'static str,
        clear_color: ColorF,
        event_loop: &ActiveEventLoop,
        proxy: &winit::event_loop::EventLoopProxy<()>,
    ) -> Self {
        let window_attrs = winit::window::Window::default_attributes()
            .with_title(name)
            .with_inner_size(LogicalSize::new(800.0_f64, 600.0_f64));

        let template = ConfigTemplateBuilder::new().with_depth_size(24);

        let (window, gl_config) = DisplayBuilder::new()
            .with_window_attributes(Some(window_attrs))
            .build(event_loop, template, |configs| {
                configs.reduce(|acc, config| {
                    if config.num_samples() > acc.num_samples() { config } else { acc }
                }).unwrap()
            })
            .expect("failed to create GL display and window");

        let window = window.unwrap();
        let gl_display = gl_config.display();

        let raw_window_handle: RawWindowHandle = window
            .window_handle()
            .expect("failed to get window handle")
            .as_raw();

        let (not_current_ctx, is_gles) = {
            let gl_attrs = ContextAttributesBuilder::new()
                .with_context_api(ContextApi::OpenGl(Some(Version::new(32))))
                .build(Some(raw_window_handle));
            match unsafe { gl_display.create_context(&gl_config, &gl_attrs) } {
                Ok(ctx) => (ctx, false),
                Err(_) => {
                    let gles_attrs = ContextAttributesBuilder::new()
                        .with_context_api(ContextApi::Gles(Some(Version::new(30))))
                        .build(Some(raw_window_handle));
                    let ctx = unsafe { gl_display.create_context(&gl_config, &gles_attrs) }
                        .expect("failed to create GLES context");
                    (ctx, true)
                }
            }
        };

        let physical_size = window.inner_size();
        let surface_attrs = SurfaceAttributesBuilder::<WindowSurface>::new()
            .build(
                raw_window_handle,
                NonZeroU32::new(physical_size.width.max(1)).unwrap(),
                NonZeroU32::new(physical_size.height.max(1)).unwrap(),
            );

        let gl_surface = unsafe {
            gl_display
                .create_window_surface(&gl_config, &surface_attrs)
                .expect("failed to create GL surface")
        };

        let gl_context = not_current_ctx
            .make_current(&gl_surface)
            .expect("failed to make GL context current");

        let gl = load_gl_fns(is_gles, &gl_display);

        let opts = webrender::WebRenderOptions {
            clear_color,
            ..webrender::WebRenderOptions::default()
        };

        let device_size = {
            let size = window.inner_size();
            DeviceIntSize::new(size.width as i32, size.height as i32)
        };
        let notifier = Box::new(Notifier::new(proxy.clone()));
        let (renderer, sender) = webrender::create_webrender_instance(gl.clone(), notifier, opts, None).unwrap();
        let mut api = sender.create_api();
        let document_id = api.add_document(device_size);

        let epoch = Epoch(0);
        let pipeline_id = PipelineId(00);
        let mut txn = Transaction::new();

        let font_key = api.generate_font_key();
        let font_bytes = load_file("../wrench/reftests/text/FreeSans.ttf");
        txn.add_raw_font(font_key, font_bytes, 0);

        let font_instance_key = api.generate_font_instance_key();
        txn.add_font_instance(font_instance_key, font_key, 32.0, None, None, Vec::new());

        api.send_transaction(document_id, txn);

        Window {
            window,
            gl_surface,
            gl_context,
            renderer,
            name,
            epoch,
            pipeline_id,
            document_id,
            api,
            font_instance_key,
        }
    }

    fn tick(&mut self) -> bool {
        let device_size = {
            let size = self.window.inner_size();
            DeviceIntSize::new(size.width as i32, size.height as i32)
        };
        let mut txn = Transaction::new();
        let mut builder = DisplayListBuilder::new(self.pipeline_id);
        let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
        builder.begin();

        builder.push_simple_stacking_context(
            space_and_clip.spatial_id,
            PrimitiveFlags::IS_BACKFACE_VISIBLE,
        );

        builder.push_rect(
            &CommonItemProperties::new(
                LayoutRect::from_origin_and_size(
                    LayoutPoint::new(100.0200.0),
                    LayoutSize::new(100.0200.0),
                ),
                space_and_clip,
            ),
            LayoutRect::from_origin_and_size(
                LayoutPoint::new(100.0200.0),
                LayoutSize::new(100.0200.0),
            ),
            ColorF::new(0.01.00.01.0));

        let text_bounds = LayoutRect::from_origin_and_size(
            LayoutPoint::new(100.050.0),
            LayoutSize::new(700.0200.0)
        );
        let glyphs = vec![
            GlyphInstance {
                index: 48,
                point: LayoutPoint::new(100.0100.0),
            },
            GlyphInstance {
                index: 68,
                point: LayoutPoint::new(150.0100.0),
            },
            GlyphInstance {
                index: 80,
                point: LayoutPoint::new(200.0100.0),
            },
            GlyphInstance {
                index: 82,
                point: LayoutPoint::new(250.0100.0),
            },
            GlyphInstance {
                index: 81,
                point: LayoutPoint::new(300.0100.0),
            },
            GlyphInstance {
                index: 3,
                point: LayoutPoint::new(350.0100.0),
            },
            GlyphInstance {
                index: 86,
                point: LayoutPoint::new(400.0100.0),
            },
            GlyphInstance {
                index: 79,
                point: LayoutPoint::new(450.0100.0),
            },
            GlyphInstance {
                index: 72,
                point: LayoutPoint::new(500.0100.0),
            },
            GlyphInstance {
                index: 83,
                point: LayoutPoint::new(550.0100.0),
            },
            GlyphInstance {
                index: 87,
                point: LayoutPoint::new(600.0100.0),
            },
            GlyphInstance {
                index: 17,
                point: LayoutPoint::new(650.0100.0),
            },
        ];

        builder.push_text(
            &CommonItemProperties::new(
                text_bounds,
                space_and_clip,
            ),
            text_bounds,
            &glyphs,
            self.font_instance_key,
            ColorF::new(1.01.00.01.0),
            None,
        );

        builder.pop_stacking_context();

        txn.set_display_list(
            self.epoch,
            builder.end(),
        );
        txn.set_root_pipeline(self.pipeline_id);
        txn.generate_frame(0truefalse, RenderReasons::empty());
        self.api.send_transaction(self.document_id, txn);

        self.renderer.update();
        self.renderer.render(device_size, 0).unwrap();
        self.gl_surface.swap_buffers(&self.gl_context).ok();

        false
    }

    fn handle_event(&mut self, event: WindowEvent) -> bool {
        match event {
            WindowEvent::CloseRequested => return true,
            WindowEvent::KeyboardInput {
                event: KeyEvent {
                    state: ElementState::Pressed,
                    ref logical_key,
                    ..
                },
                ..
            } => {
                match logical_key.as_ref() {
                    Key::Named(NamedKey::Escape) => return true,
                    Key::Character("p") | Key::Character("P") => {
                        println!("set flags {}"self.name);
                        self.api.send_debug_cmd(DebugCommand::SetFlags(DebugFlags::PROFILER_DBG));
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        false
    }

    fn deinit(self) {
        self.renderer.deinit();
    }
}

struct MultiWindowApp {
    proxy: winit::event_loop::EventLoopProxy<()>,
    win1: Option<Window>,
    win2: Option<Window>,
}

impl ApplicationHandler for MultiWindowApp {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        if self.win1.is_some() {
            return;
        }
        self.win1 = Some(Window::new("window1", ColorF::new(0.30.00.01.0), event_loop, &n style='color:red'>self.proxy));
        self.win2 = Some(Window::new("window2", ColorF::new(0.00.30.01.0), event_loop, &n style='color:red'>self.proxy));
    }

    fn window_event(
        &mut self,
        event_loop: &ActiveEventLoop,
        window_id: winit::window::WindowId,
        event: WindowEvent,
    ) {
        let win = if self.win1.as_ref().map_or(false, |w| w.window.id() == window_id) {
            self.win1.as_mut()
        } else if self.win2.as_ref().map_or(false, |w| w.window.id() == window_id) {
            self.win2.as_mut()
        } else {
            None
        };

        if let Some(win) = win {
            if win.handle_event(event) {
                if let Some(w) = self.win1.take() { w.deinit(); }
                if let Some(w) = self.win2.take() { w.deinit(); }
                event_loop.exit();
            }
        }
    }

    fn user_event(&mut self, _event_loop: &ActiveEventLoop, _event: ()) {
        if let Some(ref mut win) = self.win1 { win.tick(); }
        if let Some(ref mut win) = self.win2 { win.tick(); }
    }
}

fn main() {
    let event_loop = EventLoop::with_user_event()
        .build()
        .expect("failed to create event loop");

    let proxy = event_loop.create_proxy();

    let mut app = MultiWindowApp {
        proxy,
        win1: None,
        win2: None,
    };

    event_loop.run_app(&mut app).expect("event loop error");
}

fn load_file(name: &str) -> Vec<u8> {
    let mut file = File::open(name).unwrap();
    let mut buffer = vec![];
    file.read_to_end(&mut buffer).unwrap();
    buffer
}

Messung V0.5 in Prozent
C=61 H=97 G=80

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.