Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/khronos-egl/examples/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  wayland-static.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

extern crate khronos_egl as egl;

use egl::API as egl;
use gl::types::{GLboolean, GLchar, GLenum, GLint, GLuint, GLvoid};
use std::ffi::CStr;
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use wayland_client::{
 protocol::{wl_compositor::WlCompositor, wl_surface::WlSurface},
 DispatchData, Display, EventQueue, Main,
};

use wayland_protocols::xdg_shell::client::{
 xdg_surface::{self, XdgSurface},
 xdg_wm_base::{self, XdgWmBase},
};

fn process_xdg_event(xdg: Main<XdgWmBase>, event: xdg_wm_base::Event, _dd: DispatchData) {
 use xdg_wm_base::Event::*;

 match event {
  Ping { serial } => xdg.pong(serial),
  _ => (),
 }
}

struct DisplayConnection {
 display: Display,
 event_queue: EventQueue,
 compositor: Main<WlCompositor>,
 xdg: Main<XdgWmBase>,
}

fn setup_wayland() -> DisplayConnection {
 let display =
  wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
 let mut event_queue = display.create_event_queue();
 let attached_display = display.clone().attach(event_queue.token());

 let globals = wayland_client::GlobalManager::new(&attached_display);

 // Roundtrip to retrieve the globals list
 event_queue
  .sync_roundtrip(&mut (), |_, _, _| unreachable!())
  .unwrap();

 // Get the compositor.
 let compositor: Main<WlCompositor> = globals.instantiate_exact(1).unwrap();

 // Xdg protocol.
 let xdg: Main<XdgWmBase> = globals.instantiate_exact(1).unwrap();
 xdg.quick_assign(process_xdg_event);

 DisplayConnection {
  display,
  event_queue,
  compositor,
  xdg,
 }
}

fn setup_egl(display: &Display) -> egl::Display {
 let egl_display = unsafe {
  egl.get_display(display.get_display_ptr() as *mut std::ffi::c_void)
   .unwrap()
 };

 egl.initialize(egl_display).unwrap();
 egl_display
}

fn create_context(display: egl::Display) -> (egl::Context, egl::Config) {
 let attributes = [
  egl::RED_SIZE,
  8,
  egl::GREEN_SIZE,
  8,
  egl::BLUE_SIZE,
  8,
  egl::NONE,
 ];

 let config = egl
  .choose_first_config(display, &attributes)
  .expect("unable to choose an EGL configuration")
  .expect("no EGL configuration found");

 let context_attributes = [
  egl::CONTEXT_MAJOR_VERSION,
  4,
  egl::CONTEXT_MINOR_VERSION,
  0,
  egl::CONTEXT_OPENGL_PROFILE_MASK,
  egl::CONTEXT_OPENGL_CORE_PROFILE_BIT,
  egl::NONE,
 ];

 let context = egl
  .create_context(display, config, None, &context_attributes)
  .expect("unable to create an EGL context");

 (context, config)
}

struct Surface {
 handle: Main<WlSurface>,
 initialized: AtomicBool,
}

fn create_surface(
 ctx: &DisplayConnection,
 egl_display: egl::Display,
 egl_context: egl::Context,
 egl_config: egl::Config,
 width: i32,
 height: i32,
) -> Arc<Surface> {
 let wl_surface = ctx.compositor.create_surface();
 let xdg_surface = ctx.xdg.get_xdg_surface(&wl_surface);

 let xdg_toplevel = xdg_surface.get_toplevel();
 xdg_toplevel.set_app_id("khronos-egl-test".to_string());
 xdg_toplevel.set_title("Test".to_string());

 wl_surface.commit();
 ctx.display.flush().unwrap();

 let surface = Arc::new(Surface {
  handle: wl_surface,
  initialized: AtomicBool::new(false),
 });

 let weak_surface = Arc::downgrade(&surface);

 xdg_surface.quick_assign(
  move |xdg_surface: Main<XdgSurface>, event: xdg_surface::Event, _dd: DispatchData| {
   use xdg_surface::Event::*;

   match event {
    Configure { serial } => {
     if let Some(surface) = weak_surface.upgrade() {
      if !surface.initialized.swap(true, Ordering::Relaxed) {
       let wl_egl_surface =
        wayland_egl::WlEglSurface::new(&surface.handle, width, height);

       let egl_surface = unsafe {
        egl.create_window_surface(
         egl_display,
         egl_config,
         wl_egl_surface.ptr() as egl::NativeWindowType,
         None,
        )
        .expect("unable to create an EGL surface")
       };

       egl.make_current(
        egl_display,
        Some(egl_surface),
        Some(egl_surface),
        Some(egl_context),
       )
       .expect("unable to bind the context");

       render();

       egl.swap_buffers(egl_display, egl_surface)
        .expect("unable to post the surface content");

       xdg_surface.ack_configure(serial);
      }
     }
    }
    _ => (),
   }
  },
 );

 surface
}

fn main() {
 // Setup Open GL.
 egl.bind_api(egl::OPENGL_API)
  .expect("unable to select OpenGL API");
 gl::load_with(|name| egl.get_proc_address(name).unwrap() as *const std::ffi::c_void);

 // Setup the Wayland client.
 let mut ctx = setup_wayland();

 // Setup EGL.
 let egl_display = setup_egl(&ctx.display);
 let (egl_context, egl_config) = create_context(egl_display);

 // Create a surface.
 // Note that it must be kept alive to the end of execution.
 let _surface = create_surface(&ctx, egl_display, egl_context, egl_config, 800, 600);

 loop {
  ctx.event_queue
   .dispatch(&mut (), |_, _, _| { /* we ignore unfiltered messages */ })
   .unwrap();
 }
}

const VERTEX: &'static [GLint; 8] = &[-1, -1, 1, -1, 1, 1, -1, 1];

const INDEXES: &'static [GLuint; 4] = &[0, 1, 2, 3];

const VERTEX_SHADER: &[u8] = b"#version 400
in vec2 position;

void main() {
 gl_Position = vec4(position, 0.0f, 1.0f);
}
\0";

const FRAGMENT_SHADER: &[u8] = b"#version 400
out vec4 color;

void main() {
 color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
\0";

fn render() {
 unsafe {
  let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
  check_gl_errors();
  let src = CStr::from_bytes_with_nul_unchecked(VERTEX_SHADER).as_ptr();
  gl::ShaderSource(vertex_shader, 1, (&[src]).as_ptr(), ptr::null());
  check_gl_errors();
  gl::CompileShader(vertex_shader);
  check_shader_status(vertex_shader);

  let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
  check_gl_errors();
  let src = CStr::from_bytes_with_nul_unchecked(FRAGMENT_SHADER).as_ptr();
  gl::ShaderSource(fragment_shader, 1, (&[src]).as_ptr(), ptr::null());
  check_gl_errors();
  gl::CompileShader(fragment_shader);
  check_shader_status(fragment_shader);

  let program = gl::CreateProgram();
  check_gl_errors();
  gl::AttachShader(program, vertex_shader);
  check_gl_errors();
  gl::AttachShader(program, fragment_shader);
  check_gl_errors();
  gl::LinkProgram(program);
  check_gl_errors();
  gl::UseProgram(program);
  check_gl_errors();

  let mut buffer = 0;
  gl::GenBuffers(1, &mut buffer);
  check_gl_errors();
  gl::BindBuffer(gl::ARRAY_BUFFER, buffer);
  check_gl_errors();
  gl::BufferData(
   gl::ARRAY_BUFFER,
   8 * 4,
   VERTEX.as_ptr() as *const std::ffi::c_void,
   gl::STATIC_DRAW,
  );
  check_gl_errors();

  let mut vertex_input = 0;
  gl::GenVertexArrays(1, &mut vertex_input);
  check_gl_errors();
  gl::BindVertexArray(vertex_input);
  check_gl_errors();
  gl::EnableVertexAttribArray(0);
  check_gl_errors();
  gl::VertexAttribPointer(0, 2, gl::INT, gl::FALSE as GLboolean, 0, 0 as *const GLvoid);
  check_gl_errors();

  let mut indexes = 0;
  gl::GenBuffers(1, &mut indexes);
  check_gl_errors();
  gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, indexes);
  check_gl_errors();
  gl::BufferData(
   gl::ELEMENT_ARRAY_BUFFER,
   4 * 4,
   INDEXES.as_ptr() as *const std::ffi::c_void,
   gl::STATIC_DRAW,
  );
  check_gl_errors();

  gl::DrawElements(gl::TRIANGLE_FAN, 4, gl::UNSIGNED_INT, std::ptr::null());
  check_gl_errors();
 }
}

fn format_error(e: GLenum) -> &'static str {
 match e {
  gl::NO_ERROR => "No error",
  gl::INVALID_ENUM => "Invalid enum",
  gl::INVALID_VALUE => "Invalid value",
  gl::INVALID_OPERATION => "Invalid operation",
  gl::INVALID_FRAMEBUFFER_OPERATION => "Invalid framebuffer operation",
  gl::OUT_OF_MEMORY => "Out of memory",
  gl::STACK_UNDERFLOW => "Stack underflow",
  gl::STACK_OVERFLOW => "Stack overflow",
  _ => "Unknown error",
 }
}

pub fn check_gl_errors() {
 unsafe {
  match gl::GetError() {
   gl::NO_ERROR => (),
   e => {
    panic!("OpenGL error: {}", format_error(e))
   }
  }
 }
}

unsafe fn check_shader_status(shader: GLuint) {
 let mut status = gl::FALSE as GLint;
 gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
 if status != (gl::TRUE as GLint) {
  let mut len = 0;
  gl::GetProgramiv(shader, gl::INFO_LOG_LENGTH, &mut len);
  if len > 0 {
   let mut buf = Vec::with_capacity(len as usize);
   buf.set_len((len as usize) - 1); // subtract 1 to skip the trailing null character
   gl::GetProgramInfoLog(
    shader,
    len,
    ptr::null_mut(),
    buf.as_mut_ptr() as *mut GLchar,
   );

   let log = String::from_utf8(buf).unwrap();
   eprintln!("shader compilation log:\n{}", log);
  }

  panic!("shader compilation failed");
 }
}

[ Dauer der Verarbeitung: 0.29 Sekunden  ]