Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  raw-gles.rs   Sprache: unbekannt

 
//! This example shows interop with raw GLES contexts -
//! the ability to hook up wgpu-hal to an existing context and draw into it.
//!
//! Emscripten build:
//! 1. install emsdk
//! 2. build this example with cargo:
//!    EMCC_CFLAGS="-g -s ERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry -s FULL_ES3=1" cargo build --example raw-gles --target wasm32-unknown-emscripten
//! 3. copy raw-gles.em.html into target directory and open it in browser:
//!    cp wgpu-hal/examples/raw-gles.em.html target/wasm32-unknown-emscripten/debug/examples

extern crate wgpu_hal as hal;

#[cfg(not(any(target_arch = "wasm32", target_os = "ios", target_os = "visionos")))]
fn main() {
    use std::{ffi::CString, num::NonZeroU32};

    use glutin::{
        config::GlConfig as _,
        context::{NotCurrentGlContext as _, PossiblyCurrentGlContext as _, Version},
        display::{GetGlDisplay as _, GlDisplay as _},
        surface::GlSurface as _,
    };
    use glutin_winit::GlWindow as _;
    use rwh_05::HasRawWindowHandle as _;

    env_logger::init();
    println!("Initializing external GL context");

    let event_loop = winit::event_loop::EventLoop::new().unwrap();
    // Only Windows requires the window to be present before creating the display.
    // Other platforms don't really need one.
    let window_builder = cfg!(windows).then(|| {
        winit::window::WindowBuilder::new()
            .with_title("WGPU raw GLES example (press Escape to exit)")
    });

    // The template will match only the configurations supporting rendering
    // to Windows.
    let template = glutin::config::ConfigTemplateBuilder::new();

    let display_builder = glutin_winit::DisplayBuilder::new().with_window_builder(window_builder);

    // Find the config with the maximum number of samples, so our triangle will be
    // smooth.
    pub fn gl_config_picker(
        configs: Box<dyn Iterator<Item = glutin::config::Config> + '_>,
    ) -> glutin::config::Config {
        configs
            .reduce(|accum, config| {
                if config.num_samples() > accum.num_samples() {
                    config
                } else {
                    accum
                }
            })
            .expect("Failed to find a matching config")
    }

    let (mut window, gl_config) = display_builder
        .build(&event_loop, template, gl_config_picker)
        .expect("Failed to build window and config from display");

    println!("Picked a config with {} samples", gl_config.num_samples());

    let raw_window_handle = window.as_ref().map(|window| window.raw_window_handle());

    // XXX The display could be obtained from any object created by it, so we can
    // query it from the config.
    let gl_display = gl_config.display();

    // Glutin tries to create an OpenGL context by default.  Force it to use any version of GLES.
    let context_attributes = glutin::context::ContextAttributesBuilder::new()
        // WGPU expects GLES 3.0+.
        .with_context_api(glutin::context::ContextApi::Gles(Some(Version::new(3, 0))))
        .build(raw_window_handle);

    let mut not_current_gl_context = Some(unsafe {
        gl_display
            .create_context(&gl_config, &context_attributes)
            .expect("failed to create context")
    });

    let mut state = None;

    // Only needs to be loaded once
    let mut exposed = None;

    event_loop
        .run(move |event, window_target| {
            use winit::{
                event::{Event, KeyEvent, WindowEvent},
                event_loop::ControlFlow,
                keyboard::{Key, NamedKey},
            };
            window_target.set_control_flow(ControlFlow::Wait);

            match event {
                // Event::LoopExiting => (),
                Event::WindowEvent {
                    window_id: _,
                    event:
                        WindowEvent::CloseRequested
                        | WindowEvent::KeyboardInput {
                            event:
                                KeyEvent {
                                    logical_key: Key::Named(NamedKey::Escape),
                                    ..
                                },
                            ..
                        },
                } => window_target.exit(),
                Event::Resumed => {
                    let window = window.take().unwrap_or_else(|| {
                        let window_builder = winit::window::WindowBuilder::new()
                            .with_title("WGPU raw GLES example (press Escape to exit)");
                        glutin_winit::finalize_window(window_target, window_builder, &gl_config)
                            .unwrap()
                    });

                    let attrs = window.build_surface_attributes(Default::default());
                    let gl_surface = unsafe {
                        gl_config
                            .display()
                            .create_window_surface(&gl_config, &attrs)
                            .expect("Cannot create GL WindowSurface")
                    };

                    // Make it current.
                    let gl_context = not_current_gl_context
                        .take()
                        .unwrap()
                        .make_current(&gl_surface)
                        .expect("GL context cannot be made current with WindowSurface");

                    // The context needs to be current for the Renderer to set up shaders and
                    // buffers. It also performs function loading, which needs a current context on
                    // WGL.
                    println!("Hooking up to wgpu-hal");
                    exposed.get_or_insert_with(|| {
                        unsafe {
                            <hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
                                // XXX: On WGL this should only be called after the context was made current
                                gl_config
                                    .display()
                                    .get_proc_address(&CString::new(name).expect(name))
                            })
                        }
                        .expect("GL adapter can't be initialized")
                    });

                    assert!(state.replace((gl_context, gl_surface, window)).is_none());
                }
                Event::Suspended => {
                    // This event is only raised on Android, where the backing NativeWindow for a GL
                    // Surface can appear and disappear at any moment.
                    println!("Android window removed");

                    // Destroy the GL Surface and un-current the GL Context before ndk-glue releases
                    // the window back to the system.
                    let (gl_context, ..) = state.take().unwrap();
                    assert!(not_current_gl_context
                        .replace(gl_context.make_not_current().unwrap())
                        .is_none());
                }
                Event::WindowEvent {
                    window_id: _,
                    event: WindowEvent::Resized(size),
                } => {
                    if size.width != 0 && size.height != 0 {
                        // Some platforms like EGL require resizing GL surface to update the size
                        // Notable platforms here are Wayland and macOS, other don't require it
                        // and the function is no-op, but it's wise to resize it for portability
                        // reasons.
                        if let Some((gl_context, gl_surface, _)) = &state {
                            gl_surface.resize(
                                gl_context,
                                NonZeroU32::new(size.width).unwrap(),
                                NonZeroU32::new(size.height).unwrap(),
                            );
                            // XXX: If there's a state for fill_screen(), this would need to be updated too.
                        }
                    }
                }
                Event::WindowEvent {
                    window_id: _,
                    event: WindowEvent::RedrawRequested,
                } => {
                    if let (Some(exposed), Some((gl_context, gl_surface, window))) =
                        (&exposed, &state)
                    {
                        let inner_size = window.inner_size();

                        fill_screen(exposed, inner_size.width, inner_size.height);

                        println!("Showing the window");
                        gl_surface
                            .swap_buffers(gl_context)
                            .expect("Failed to swap buffers");
                    }
                }
                _ => (),
            }
        })
        .expect("Couldn't run event loop");
}

#[cfg(target_os = "emscripten")]
fn main() {
    env_logger::init();

    println!("Initializing external GL context");
    let egl = khronos_egl::Instance::new(khronos_egl::Static);
    let display = unsafe { egl.get_display(khronos_egl::DEFAULT_DISPLAY) }.unwrap();
    egl.initialize(display)
        .expect("unable to initialize display");

    let attributes = [
        khronos_egl::RED_SIZE,
        8,
        khronos_egl::GREEN_SIZE,
        8,
        khronos_egl::BLUE_SIZE,
        8,
        khronos_egl::NONE,
    ];

    let config = egl
        .choose_first_config(display, &attributes)
        .unwrap()
        .expect("unable to choose config");
    let surface = unsafe {
        let window = std::ptr::null_mut::<std::ffi::c_void>();
        egl.create_window_surface(display, config, window, None)
    }
    .expect("unable to create surface");

    let context_attributes = [khronos_egl::CONTEXT_CLIENT_VERSION, 3, khronos_egl::NONE];

    let gl_context = egl
        .create_context(display, config, None, &context_attributes)
        .expect("unable to create context");
    egl.make_current(display, Some(surface), Some(surface), Some(gl_context))
        .expect("can't make context current");

    println!("Hooking up to wgpu-hal");
    let exposed = unsafe {
        <hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
            egl.get_proc_address(name)
                .map_or(std::ptr::null(), |p| p as *const _)
        })
    }
    .expect("GL adapter can't be initialized");

    fill_screen(&exposed, 640, 400);
}

#[cfg(any(
    all(target_arch = "wasm32", not(target_os = "emscripten")),
    target_os = "ios",
    target_os = "visionos"
))]
fn main() {
    eprintln!("This example is not supported on Windows and non-emscripten wasm32")
}

#[cfg(not(any(
    all(target_arch = "wasm32", not(target_os = "emscripten")),
    target_os = "ios",
    target_os = "visionos"
)))]
fn fill_screen(exposed: &hal::ExposedAdapter<hal::api::Gles>, width: u32, height: u32) {
    use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _};

    let od = unsafe {
        exposed.adapter.open(
            wgt::Features::empty(),
            &wgt::Limits::downlevel_defaults(),
            &wgt::MemoryHints::default(),
        )
    }
    .unwrap();

    let format = wgt::TextureFormat::Rgba8UnormSrgb;
    let texture = <hal::api::Gles as hal::Api>::Texture::default_framebuffer(format);
    let view = unsafe {
        od.device
            .create_texture_view(
                &texture,
                &hal::TextureViewDescriptor {
                    label: None,
                    format,
                    dimension: wgt::TextureViewDimension::D2,
                    usage: hal::TextureUses::COLOR_TARGET,
                    range: wgt::ImageSubresourceRange::default(),
                },
            )
            .unwrap()
    };

    println!("Filling the screen");
    let mut encoder = unsafe {
        od.device
            .create_command_encoder(&hal::CommandEncoderDescriptor {
                label: None,
                queue: &od.queue,
            })
            .unwrap()
    };
    let mut fence = unsafe { od.device.create_fence().unwrap() };
    let rp_desc = hal::RenderPassDescriptor {
        label: None,
        extent: wgt::Extent3d {
            width,
            height,
            depth_or_array_layers: 1,
        },
        sample_count: 1,
        color_attachments: &[Some(hal::ColorAttachment {
            target: hal::Attachment {
                view: &view,
                usage: hal::TextureUses::COLOR_TARGET,
            },
            resolve_target: None,
            ops: hal::AttachmentOps::STORE,
            clear_value: wgt::Color::BLUE,
        })],
        depth_stencil_attachment: None,
        multiview: None,
        timestamp_writes: None,
        occlusion_query_set: None,
    };
    unsafe {
        encoder.begin_encoding(None).unwrap();
        encoder.begin_render_pass(&rp_desc);
        encoder.end_render_pass();
        let cmd_buf = encoder.end_encoding().unwrap();
        od.queue.submit(&[&cmd_buf], &[], (&mut fence, 0)).unwrap();
    }
}

[ Dauer der Verarbeitung: 0.26 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge