autocommit 2022-04-04 23:09:39 CEST
This commit is contained in:
parent
e897d271af
commit
5f79aab15f
21 changed files with 870 additions and 731 deletions
|
|
@ -18,6 +18,7 @@ use std::io::BufWriter;
|
|||
use std::path::PathBuf;
|
||||
use std::{env, io};
|
||||
|
||||
mod egl;
|
||||
mod enums;
|
||||
mod tokens;
|
||||
mod wire;
|
||||
|
|
@ -41,6 +42,7 @@ fn main() -> anyhow::Result<()> {
|
|||
wire_dbus::main()?;
|
||||
wire_xcon::main()?;
|
||||
enums::main()?;
|
||||
egl::main()?;
|
||||
|
||||
println!("cargo:rerun-if-changed=build/build.rs");
|
||||
Ok(())
|
||||
|
|
|
|||
143
build/egl.rs
Normal file
143
build/egl.rs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
use crate::open;
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::io::Write;
|
||||
|
||||
fn write_egl_procs<W: Write>(f: &mut W) -> anyhow::Result<()> {
|
||||
let map = [
|
||||
(
|
||||
"eglGetPlatformDisplayEXT",
|
||||
"EGLDisplay",
|
||||
&[
|
||||
("platform", "EGLenum"),
|
||||
("native_display", "*mut u8"),
|
||||
("attrib_list", "*const EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglCreateImageKHR",
|
||||
"EGLImageKHR",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("ctx", "EGLContext"),
|
||||
("target", "EGLenum"),
|
||||
("buffer", "EGLClientBuffer"),
|
||||
("attrib_list", "*const EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglDestroyImageKHR",
|
||||
"EGLBoolean",
|
||||
&[("dpy", "EGLDisplay"), ("image", "EGLImageKHR")][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDmaBufFormatsEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("max_formats", "EGLint"),
|
||||
("formats", "*mut EGLint"),
|
||||
("num_formats", "*mut EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDmaBufModifiersEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("format", "EGLint"),
|
||||
("max_modifiers", "EGLint"),
|
||||
("modifiers", "*mut EGLuint64KHR"),
|
||||
("external_only", "*mut EGLBoolean"),
|
||||
("num_modifiers", "*mut EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglDebugMessageControlKHR",
|
||||
"EGLint",
|
||||
&[
|
||||
("callback", "EGLDEBUGPROCKHR"),
|
||||
("attrib_list", "*const EGLAttrib"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDisplayAttribEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("attribute", "EGLint"),
|
||||
("value", "*mut EGLAttrib"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"glEGLImageTargetRenderbufferStorageOES",
|
||||
"()",
|
||||
&[("target", "GLenum"), ("image", "GLeglImageOES")][..],
|
||||
),
|
||||
(
|
||||
"glEGLImageTargetTexture2DOES",
|
||||
"()",
|
||||
&[("target", "GLenum"), ("image", "GLeglImageOES")][..],
|
||||
),
|
||||
];
|
||||
|
||||
writeln!(f, "use std::ptr;")?;
|
||||
writeln!(f, "use super::gl::sys::*;")?;
|
||||
writeln!(f, "use super::egl::sys::*;")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "#[derive(Copy, Clone, Debug)]")?;
|
||||
writeln!(f, "pub struct ExtProc {{")?;
|
||||
for (name, _, _) in map.iter() {
|
||||
writeln!(f, " {}: *mut u8,", name)?;
|
||||
}
|
||||
writeln!(f, "}}")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "unsafe impl Sync for ExtProc {{ }}")?;
|
||||
writeln!(f, "unsafe impl Send for ExtProc {{ }}")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "impl ExtProc {{")?;
|
||||
writeln!(f, " pub fn load() -> Self {{")?;
|
||||
writeln!(f, " Self {{")?;
|
||||
for (name, _, _) in map.iter().copied() {
|
||||
writeln!(
|
||||
f,
|
||||
" {}: unsafe {{ eglGetProcAddress(\"{}\\0\".as_ptr() as _) }},",
|
||||
name, name
|
||||
)?;
|
||||
}
|
||||
writeln!(f, " }}")?;
|
||||
writeln!(f, " }}")?;
|
||||
for (name, ret, args) in map.iter().copied() {
|
||||
let mut args_names = String::new();
|
||||
let mut args_full = String::new();
|
||||
let mut args_tys = String::new();
|
||||
for (name, ty) in args.iter().copied() {
|
||||
write!(args_full, "{}: {}, ", name, ty)?;
|
||||
write!(args_names, "{}, ", name)?;
|
||||
write!(args_tys, "{}, ", ty)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
writeln!(
|
||||
f,
|
||||
" pub(super) unsafe fn {}(&self, {}) -> {} {{",
|
||||
name, args_full, ret
|
||||
)?;
|
||||
writeln!(f, " if self.{}.is_null() {{", name)?;
|
||||
writeln!(f, " panic!(\"Could not load `{}`\");", name)?;
|
||||
writeln!(f, " }}")?;
|
||||
writeln!(
|
||||
f,
|
||||
" ptr::read(&self.{} as *const *mut u8 as *const unsafe extern fn({}) -> {})({})",
|
||||
name, args_tys, ret, args_names
|
||||
)?;
|
||||
writeln!(f, " }}")?;
|
||||
}
|
||||
writeln!(f, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() -> anyhow::Result<()> {
|
||||
let mut f = open("egl_procs.rs")?;
|
||||
write_egl_procs(&mut f)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
158
build/enums.rs
158
build/enums.rs
|
|
@ -1,7 +1,6 @@
|
|||
use crate::open;
|
||||
use repc::layout::{Type, TypeVariant};
|
||||
use std::env;
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::io::Write;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
|
|
@ -9,9 +8,6 @@ use std::io::Write;
|
|||
#[path = "../src/macros.rs"]
|
||||
mod macros;
|
||||
|
||||
#[path = "../src/pixman/consts.rs"]
|
||||
mod pixman;
|
||||
|
||||
#[path = "../src/xkbcommon/consts.rs"]
|
||||
mod xkbcommon;
|
||||
|
||||
|
|
@ -51,153 +47,6 @@ fn write_ty<W: Write>(f: &mut W, vals: &[i32], ty: &str) -> anyhow::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_egl_procs<W: Write>(f: &mut W) -> anyhow::Result<()> {
|
||||
let map = [
|
||||
(
|
||||
"eglGetPlatformDisplayEXT",
|
||||
"EGLDisplay",
|
||||
&[
|
||||
("platform", "EGLenum"),
|
||||
("native_display", "*mut u8"),
|
||||
("attrib_list", "*const EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglCreateImageKHR",
|
||||
"EGLImageKHR",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("ctx", "EGLContext"),
|
||||
("target", "EGLenum"),
|
||||
("buffer", "EGLClientBuffer"),
|
||||
("attrib_list", "*const EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglDestroyImageKHR",
|
||||
"EGLBoolean",
|
||||
&[("dpy", "EGLDisplay"), ("image", "EGLImageKHR")][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDmaBufFormatsEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("max_formats", "EGLint"),
|
||||
("formats", "*mut EGLint"),
|
||||
("num_formats", "*mut EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDmaBufModifiersEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("format", "EGLint"),
|
||||
("max_modifiers", "EGLint"),
|
||||
("modifiers", "*mut EGLuint64KHR"),
|
||||
("external_only", "*mut EGLBoolean"),
|
||||
("num_modifiers", "*mut EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglDebugMessageControlKHR",
|
||||
"EGLint",
|
||||
&[
|
||||
("callback", "EGLDEBUGPROCKHR"),
|
||||
("attrib_list", "*const EGLAttrib"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDisplayAttribEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("dpy", "EGLDisplay"),
|
||||
("attribute", "EGLint"),
|
||||
("value", "*mut EGLAttrib"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDeviceStringEXT",
|
||||
"*const c::c_char",
|
||||
&[("device", "EGLDeviceEXT"), ("name", "EGLint")][..],
|
||||
),
|
||||
(
|
||||
"eglQueryDevicesEXT",
|
||||
"EGLBoolean",
|
||||
&[
|
||||
("max_devices", "EGLint"),
|
||||
("devices", "*mut EGLDeviceEXT"),
|
||||
("num_devices", "*mut EGLint"),
|
||||
][..],
|
||||
),
|
||||
(
|
||||
"glEGLImageTargetRenderbufferStorageOES",
|
||||
"()",
|
||||
&[("target", "GLenum"), ("image", "GLeglImageOES")][..],
|
||||
),
|
||||
(
|
||||
"glEGLImageTargetTexture2DOES",
|
||||
"()",
|
||||
&[("target", "GLenum"), ("image", "GLeglImageOES")][..],
|
||||
),
|
||||
];
|
||||
|
||||
writeln!(f, "use std::ptr;")?;
|
||||
writeln!(f, "use super::gl::sys::*;")?;
|
||||
writeln!(f, "use super::egl::sys::*;")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "#[derive(Copy, Clone, Debug)]")?;
|
||||
writeln!(f, "pub struct ExtProc {{")?;
|
||||
for (name, _, _) in map.iter() {
|
||||
writeln!(f, " {}: *mut u8,", name)?;
|
||||
}
|
||||
writeln!(f, "}}")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "unsafe impl Sync for ExtProc {{ }}")?;
|
||||
writeln!(f, "unsafe impl Send for ExtProc {{ }}")?;
|
||||
writeln!(f)?;
|
||||
writeln!(f, "impl ExtProc {{")?;
|
||||
writeln!(f, " pub fn load() -> Self {{")?;
|
||||
writeln!(f, " Self {{")?;
|
||||
for (name, _, _) in map.iter().copied() {
|
||||
writeln!(
|
||||
f,
|
||||
" {}: unsafe {{ eglGetProcAddress(\"{}\\0\".as_ptr() as _) }},",
|
||||
name, name
|
||||
)?;
|
||||
}
|
||||
writeln!(f, " }}")?;
|
||||
writeln!(f, " }}")?;
|
||||
for (name, ret, args) in map.iter().copied() {
|
||||
let mut args_names = String::new();
|
||||
let mut args_full = String::new();
|
||||
let mut args_tys = String::new();
|
||||
for (name, ty) in args.iter().copied() {
|
||||
write!(args_full, "{}: {}, ", name, ty)?;
|
||||
write!(args_names, "{}, ", name)?;
|
||||
write!(args_tys, "{}, ", ty)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
writeln!(
|
||||
f,
|
||||
" pub(super) unsafe fn {}(&self, {}) -> {} {{",
|
||||
name, args_full, ret
|
||||
)?;
|
||||
writeln!(f, " if self.{}.is_null() {{", name)?;
|
||||
writeln!(f, " panic!(\"Could not load `{}`\");", name)?;
|
||||
writeln!(f, " }}")?;
|
||||
writeln!(
|
||||
f,
|
||||
" ptr::read(&self.{} as *const *mut u8 as *const unsafe extern fn({}) -> {})({})",
|
||||
name, args_tys, ret, args_names
|
||||
)?;
|
||||
writeln!(f, " }}")?;
|
||||
}
|
||||
writeln!(f, "}}")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() -> anyhow::Result<()> {
|
||||
let mut f = open("libinput_tys.rs")?;
|
||||
write_ty(
|
||||
|
|
@ -270,10 +119,6 @@ pub fn main() -> anyhow::Result<()> {
|
|||
"libinput_config_accel_profile",
|
||||
)?;
|
||||
|
||||
let mut f = open("pixman_tys.rs")?;
|
||||
write_ty(&mut f, pixman::FORMATS, "PixmanFormat")?;
|
||||
write_ty(&mut f, pixman::OPS, "PixmanOp")?;
|
||||
|
||||
let mut f = open("pango_tys.rs")?;
|
||||
write_ty(&mut f, pango::CAIRO_FORMATS, "cairo_format_t")?;
|
||||
write_ty(&mut f, pango::CAIRO_STATUSES, "cairo_status_t")?;
|
||||
|
|
@ -296,8 +141,5 @@ pub fn main() -> anyhow::Result<()> {
|
|||
)?;
|
||||
write_ty(&mut f, xkbcommon::XKB_KEY_DIRECTION, "xkb_key_direction")?;
|
||||
|
||||
let mut f = open("egl_procs.rs")?;
|
||||
write_egl_procs(&mut f)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use crate::pixman;
|
||||
use crate::render::sys::{GLint, GL_BGRA_EXT, GL_UNSIGNED_BYTE};
|
||||
use crate::utils::debug_fn::debug_fn;
|
||||
use ahash::AHashMap;
|
||||
|
|
@ -9,7 +8,6 @@ use std::fmt::{Debug, Write};
|
|||
pub struct Format {
|
||||
pub name: &'static str,
|
||||
pub bpp: u32,
|
||||
pub pixman: Option<pixman::Format>,
|
||||
pub gl_format: GLint,
|
||||
pub gl_type: GLint,
|
||||
pub drm: u32,
|
||||
|
|
@ -66,7 +64,6 @@ pub static FORMATS: &[Format] = &[
|
|||
Format {
|
||||
name: "argb8888",
|
||||
bpp: 4,
|
||||
pixman: Some(pixman::A8R8G8B8),
|
||||
gl_format: GL_BGRA_EXT,
|
||||
gl_type: GL_UNSIGNED_BYTE,
|
||||
drm: ARGB8888_DRM,
|
||||
|
|
@ -76,7 +73,6 @@ pub static FORMATS: &[Format] = &[
|
|||
Format {
|
||||
name: "xrgb8888",
|
||||
bpp: 4,
|
||||
pixman: Some(pixman::X8R8G8B8),
|
||||
gl_format: GL_BGRA_EXT,
|
||||
gl_type: GL_UNSIGNED_BYTE,
|
||||
drm: XRGB8888_DRM,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::pixman::Region;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
use crate::wire::wl_region::*;
|
||||
|
|
@ -9,11 +8,12 @@ use crate::wire::WlRegionId;
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::rect::{Rect, Region, RegionBuilder};
|
||||
|
||||
pub struct WlRegion {
|
||||
id: WlRegionId,
|
||||
client: Rc<Client>,
|
||||
rect: RefCell<Region>,
|
||||
region: RefCell<RegionBuilder>,
|
||||
pub tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
|
|
@ -22,13 +22,13 @@ impl WlRegion {
|
|||
Self {
|
||||
id,
|
||||
client: client.clone(),
|
||||
rect: RefCell::new(Region::new()),
|
||||
region: Default::default(),
|
||||
tracker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn region(&self) -> Region {
|
||||
self.rect.borrow().clone()
|
||||
pub fn region(&self) -> Rc<Region> {
|
||||
self.region.borrow_mut().get()
|
||||
}
|
||||
|
||||
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
|
|
@ -42,23 +42,18 @@ impl WlRegion {
|
|||
if add.width < 0 || add.height < 0 {
|
||||
return Err(AddError::NegativeExtents);
|
||||
}
|
||||
let mut rect = self.rect.borrow_mut();
|
||||
*rect = rect.add(&Region::rect(add.x, add.y, add.width as _, add.height as _));
|
||||
let mut region = self.region.borrow_mut();
|
||||
region.add(Rect::new_sized(add.x, add.y, add.width, add.height).unwrap());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn subtract(&self, parser: MsgParser<'_, '_>) -> Result<(), SubtractError> {
|
||||
let subtract: Subtract = self.client.parse(self, parser)?;
|
||||
if subtract.width < 0 || subtract.height < 0 {
|
||||
let req: Subtract = self.client.parse(self, parser)?;
|
||||
if req.width < 0 || req.height < 0 {
|
||||
return Err(SubtractError::NegativeExtents);
|
||||
}
|
||||
let mut rect = self.rect.borrow_mut();
|
||||
*rect = rect.subtract(&Region::rect(
|
||||
subtract.x,
|
||||
subtract.y,
|
||||
subtract.width as _,
|
||||
subtract.height as _,
|
||||
));
|
||||
let mut region = self.region.borrow_mut();
|
||||
region.sub(Rect::new_sized(req.x, req.y, req.width, req.height).unwrap());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@ use crate::ifs::wl_surface::xdg_surface::XdgSurfaceError;
|
|||
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::pixman::Region;
|
||||
use crate::rect::Rect;
|
||||
use crate::rect::{Rect, Region};
|
||||
use crate::render::Renderer;
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
|
|
@ -77,8 +76,8 @@ pub struct WlSurface {
|
|||
pub client: Rc<Client>,
|
||||
role: Cell<SurfaceRole>,
|
||||
pending: PendingState,
|
||||
input_region: Cell<Option<Region>>,
|
||||
opaque_region: Cell<Option<Region>>,
|
||||
input_region: Cell<Option<Rc<Region>>>,
|
||||
opaque_region: Cell<Option<Rc<Region>>>,
|
||||
pub extents: Cell<Rect>,
|
||||
pub buffer_abs_pos: Cell<Rect>,
|
||||
pub need_extents_update: Cell<bool>,
|
||||
|
|
@ -167,8 +166,8 @@ impl SurfaceExt for NoneSurfaceExt {
|
|||
#[derive(Default)]
|
||||
struct PendingState {
|
||||
buffer: Cell<Option<Option<(i32, i32, Rc<WlBuffer>)>>>,
|
||||
opaque_region: Cell<Option<Option<Region>>>,
|
||||
input_region: Cell<Option<Option<Region>>>,
|
||||
opaque_region: Cell<Option<Option<Rc<Region>>>>,
|
||||
input_region: Cell<Option<Option<Rc<Region>>>>,
|
||||
frame_request: RefCell<Vec<Rc<WlCallback>>>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ mod logger;
|
|||
mod logind;
|
||||
mod object;
|
||||
mod pango;
|
||||
mod pixman;
|
||||
mod rect;
|
||||
mod render;
|
||||
mod sighand;
|
||||
|
|
|
|||
110
src/pixman.rs
110
src/pixman.rs
|
|
@ -1,110 +0,0 @@
|
|||
mod consts;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/pixman_tys.rs"));
|
||||
|
||||
pub use consts::*;
|
||||
use std::ptr;
|
||||
use uapi::c;
|
||||
|
||||
#[link(name = "pixman-1")]
|
||||
#[allow(improper_ctypes)]
|
||||
extern "C" {
|
||||
fn pixman_region32_init(region: *mut Region);
|
||||
fn pixman_region32_init_rect(
|
||||
region: *mut Region,
|
||||
x: c::c_int,
|
||||
y: c::c_int,
|
||||
width: c::c_uint,
|
||||
height: c::c_uint,
|
||||
);
|
||||
fn pixman_region32_fini(region: *mut Region);
|
||||
fn pixman_region32_copy(dst: *mut Region, src: *const Region);
|
||||
fn pixman_region32_union(dst: *mut Region, a: *const Region, b: *const Region);
|
||||
fn pixman_region32_subtract(dst: *mut Region, a: *const Region, b: *const Region);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
pub struct Box32 {
|
||||
pub x1: i32,
|
||||
pub y1: i32,
|
||||
pub x2: i32,
|
||||
pub y2: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
pub struct Color {
|
||||
red: u16,
|
||||
green: u16,
|
||||
blue: u16,
|
||||
alpha: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct RegionData {
|
||||
size: c::c_long,
|
||||
num_rects: c::c_long,
|
||||
// rects: [Box32; size],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Region {
|
||||
extents: Box32,
|
||||
data: *mut RegionData,
|
||||
}
|
||||
|
||||
impl Region {
|
||||
pub fn new() -> Self {
|
||||
let mut slf = Region {
|
||||
extents: Default::default(),
|
||||
data: ptr::null_mut(),
|
||||
};
|
||||
unsafe {
|
||||
pixman_region32_init(&mut slf);
|
||||
}
|
||||
slf
|
||||
}
|
||||
|
||||
pub fn rect(x: i32, y: i32, width: i32, height: i32) -> Self {
|
||||
let mut new = Region::new();
|
||||
unsafe {
|
||||
pixman_region32_init_rect(&mut new, x as _, y as _, width as _, height as _);
|
||||
}
|
||||
new
|
||||
}
|
||||
|
||||
pub fn add(&self, region: &Self) -> Self {
|
||||
let mut new = Region::new();
|
||||
unsafe {
|
||||
pixman_region32_union(&mut new, self, region);
|
||||
}
|
||||
new
|
||||
}
|
||||
|
||||
pub fn subtract(&self, region: &Self) -> Self {
|
||||
let mut new = Region::new();
|
||||
unsafe {
|
||||
pixman_region32_subtract(&mut new, self, region);
|
||||
}
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Region {
|
||||
fn clone(&self) -> Self {
|
||||
let mut new = Region::new();
|
||||
unsafe {
|
||||
pixman_region32_copy(&mut new, self);
|
||||
}
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Region {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
pixman_region32_fini(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub const fn format(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> i32 {
|
||||
((bpp << 24) | (ty << 16) | (a << 12) | (r << 8) | (g << 4) | b) as i32
|
||||
}
|
||||
|
||||
pub const fn format_byte(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> i32 {
|
||||
(((bpp >> 3) << 24)
|
||||
| (3 << 22)
|
||||
| (ty << 16)
|
||||
| ((a >> 3) << 12)
|
||||
| ((r >> 3) << 8)
|
||||
| ((g >> 3) << 4)
|
||||
| (b >> 3)) as i32
|
||||
}
|
||||
|
||||
pub const fn format_reshift(val: u32, ofs: u32, num: u32) -> u32 {
|
||||
((val >> (ofs)) & ((1 << (num)) - 1)) << ((val >> 22) & 3)
|
||||
}
|
||||
|
||||
pub const fn format_bpp(f: u32) -> u32 {
|
||||
format_reshift(f, 24, 8)
|
||||
}
|
||||
|
||||
pub const fn format_shift(f: u32) -> u32 {
|
||||
(f >> 22) & 3
|
||||
}
|
||||
|
||||
pub const fn format_type(f: u32) -> u32 {
|
||||
(f >> 16) & 0x3f
|
||||
}
|
||||
|
||||
pub const fn format_a(f: u32) -> u32 {
|
||||
format_reshift(f, 12, 4)
|
||||
}
|
||||
|
||||
pub const fn format_r(f: u32) -> u32 {
|
||||
format_reshift(f, 8, 4)
|
||||
}
|
||||
|
||||
pub const fn format_g(f: u32) -> u32 {
|
||||
format_reshift(f, 4, 4)
|
||||
}
|
||||
|
||||
pub const fn format_b(f: u32) -> u32 {
|
||||
format_reshift(f, 0, 4)
|
||||
}
|
||||
|
||||
pub const fn format_rgb(f: u32) -> u32 {
|
||||
f & 0xfff
|
||||
}
|
||||
|
||||
pub const fn format_vis(f: u32) -> u32 {
|
||||
f & 0xffff
|
||||
}
|
||||
|
||||
pub const fn format_depth(f: u32) -> u32 {
|
||||
format_a(f) + format_r(f) + format_g(f) + format_b(f)
|
||||
}
|
||||
|
||||
pub const TYPE_OTHER: u32 = 0;
|
||||
pub const TYPE_A: u32 = 1;
|
||||
pub const TYPE_ARGB: u32 = 2;
|
||||
pub const TYPE_ABGR: u32 = 3;
|
||||
pub const TYPE_COLOR: u32 = 4;
|
||||
pub const TYPE_GRAY: u32 = 5;
|
||||
pub const TYPE_YUY2: u32 = 6;
|
||||
pub const TYPE_YV12: u32 = 7;
|
||||
pub const TYPE_BGRA: u32 = 8;
|
||||
pub const TYPE_RGBA: u32 = 9;
|
||||
pub const TYPE_ARGB_SRGB: u32 = 10;
|
||||
pub const TYPE_RGBA_FLOAT: u32 = 11;
|
||||
|
||||
pub const fn format_color(f: u32) -> bool {
|
||||
format_type(f) == TYPE_ARGB
|
||||
|| format_type(f) == TYPE_ABGR
|
||||
|| format_type(f) == TYPE_BGRA
|
||||
|| format_type(f) == TYPE_RGBA
|
||||
|| format_type(f) == TYPE_RGBA_FLOAT
|
||||
}
|
||||
|
||||
cenum! {
|
||||
Format, FORMATS;
|
||||
|
||||
RGBA_FLOAT = format_byte(128, TYPE_RGBA_FLOAT, 32, 32, 32, 32),
|
||||
RGB_FLOAT = format_byte(96, TYPE_RGBA_FLOAT, 0, 32, 32, 32),
|
||||
A8R8G8B8 = format(32, TYPE_ARGB, 8, 8, 8, 8),
|
||||
X8R8G8B8 = format(32, TYPE_ARGB, 0, 8, 8, 8),
|
||||
A8B8G8R8 = format(32, TYPE_ABGR, 8, 8, 8, 8),
|
||||
X8B8G8R8 = format(32, TYPE_ABGR, 0, 8, 8, 8),
|
||||
B8G8R8A8 = format(32, TYPE_BGRA, 8, 8, 8, 8),
|
||||
B8G8R8X8 = format(32, TYPE_BGRA, 0, 8, 8, 8),
|
||||
R8G8B8A8 = format(32, TYPE_RGBA, 8, 8, 8, 8),
|
||||
R8G8B8X8 = format(32, TYPE_RGBA, 0, 8, 8, 8),
|
||||
X14R6G6B6 = format(32, TYPE_ARGB, 0, 6, 6, 6),
|
||||
X2R10G10B10 = format(32, TYPE_ARGB, 0, 10, 10, 10),
|
||||
A2R10G10B10 = format(32, TYPE_ARGB, 2, 10, 10, 10),
|
||||
X2B10G10R10 = format(32, TYPE_ABGR, 0, 10, 10, 10),
|
||||
A2B10G10R10 = format(32, TYPE_ABGR, 2, 10, 10, 10),
|
||||
A8R8G8B8_SRGB = format(32, TYPE_ARGB_SRGB, 8, 8, 8, 8),
|
||||
R8G8B8 = format(24, TYPE_ARGB, 0, 8, 8, 8),
|
||||
B8G8R8 = format(24, TYPE_ABGR, 0, 8, 8, 8),
|
||||
R5G6B5 = format(16, TYPE_ARGB, 0, 5, 6, 5),
|
||||
B5G6R5 = format(16, TYPE_ABGR, 0, 5, 6, 5),
|
||||
A1R5G5B5 = format(16, TYPE_ARGB, 1, 5, 5, 5),
|
||||
X1R5G5B5 = format(16, TYPE_ARGB, 0, 5, 5, 5),
|
||||
A1B5G5R5 = format(16, TYPE_ABGR, 1, 5, 5, 5),
|
||||
X1B5G5R5 = format(16, TYPE_ABGR, 0, 5, 5, 5),
|
||||
A4R4G4B4 = format(16, TYPE_ARGB, 4, 4, 4, 4),
|
||||
X4R4G4B4 = format(16, TYPE_ARGB, 0, 4, 4, 4),
|
||||
A4B4G4R4 = format(16, TYPE_ABGR, 4, 4, 4, 4),
|
||||
X4B4G4R4 = format(16, TYPE_ABGR, 0, 4, 4, 4),
|
||||
A8 = format(8, TYPE_A, 8, 0, 0, 0),
|
||||
R3G3B2 = format(8, TYPE_ARGB, 0, 3, 3, 2),
|
||||
B2G3R3 = format(8, TYPE_ABGR, 0, 3, 3, 2),
|
||||
A2R2G2B2 = format(8, TYPE_ARGB, 2, 2, 2, 2),
|
||||
A2B2G2R2 = format(8, TYPE_ABGR, 2, 2, 2, 2),
|
||||
C8 = format(8, TYPE_COLOR, 0, 0, 0, 0),
|
||||
G8 = format(8, TYPE_GRAY, 0, 0, 0, 0),
|
||||
X4A4 = format(8, TYPE_A, 4, 0, 0, 0),
|
||||
X4C4 = format(8, TYPE_COLOR, 0, 0, 0, 0),
|
||||
X4G4 = format(8, TYPE_GRAY, 0, 0, 0, 0),
|
||||
A4 = format(4, TYPE_A, 4, 0, 0, 0),
|
||||
R1G2B1 = format(4, TYPE_ARGB, 0, 1, 2, 1),
|
||||
B1G2R1 = format(4, TYPE_ABGR, 0, 1, 2, 1),
|
||||
A1R1G1B1 = format(4, TYPE_ARGB, 1, 1, 1, 1),
|
||||
A1B1G1R1 = format(4, TYPE_ABGR, 1, 1, 1, 1),
|
||||
C4 = format(4, TYPE_COLOR, 0, 0, 0, 0),
|
||||
G4 = format(4, TYPE_GRAY, 0, 0, 0, 0),
|
||||
A1 = format(1, TYPE_A, 1, 0, 0, 0),
|
||||
G1 = format(1, TYPE_GRAY, 0, 0, 0, 0),
|
||||
YUY2 = format(16, TYPE_YUY2, 0, 0, 0, 0),
|
||||
YV12 = format(12, TYPE_YV12, 0, 0, 0, 0),
|
||||
}
|
||||
|
||||
cenum! {
|
||||
Op, OPS;
|
||||
|
||||
OP_CLEAR = 0x00,
|
||||
OP_SRC = 0x01,
|
||||
OP_DST = 0x02,
|
||||
OP_OVER = 0x03,
|
||||
OP_OVER_REVERSE = 0x04,
|
||||
OP_IN = 0x05,
|
||||
OP_IN_REVERSE = 0x06,
|
||||
OP_OUT = 0x07,
|
||||
OP_OUT_REVERSE = 0x08,
|
||||
OP_ATOP = 0x09,
|
||||
OP_ATOP_REVERSE = 0x0a,
|
||||
OP_XOR = 0x0b,
|
||||
OP_ADD = 0x0c,
|
||||
OP_SATURATE = 0x0d,
|
||||
OP_DISJOINT_CLEAR = 0x10,
|
||||
OP_DISJOINT_SRC = 0x11,
|
||||
OP_DISJOINT_DST = 0x12,
|
||||
OP_DISJOINT_OVER = 0x13,
|
||||
OP_DISJOINT_OVER_REVERSE = 0x14,
|
||||
OP_DISJOINT_IN = 0x15,
|
||||
OP_DISJOINT_IN_REVERSE = 0x16,
|
||||
OP_DISJOINT_OUT = 0x17,
|
||||
OP_DISJOINT_OUT_REVERSE = 0x18,
|
||||
OP_DISJOINT_ATOP = 0x19,
|
||||
OP_DISJOINT_ATOP_REVERSE = 0x1a,
|
||||
OP_DISJOINT_XOR = 0x1b,
|
||||
OP_CONJOINT_CLEAR = 0x20,
|
||||
OP_CONJOINT_SRC = 0x21,
|
||||
OP_CONJOINT_DST = 0x22,
|
||||
OP_CONJOINT_OVER = 0x23,
|
||||
OP_CONJOINT_OVER_REVERSE = 0x24,
|
||||
OP_CONJOINT_IN = 0x25,
|
||||
OP_CONJOINT_IN_REVERSE = 0x26,
|
||||
OP_CONJOINT_OUT = 0x27,
|
||||
OP_CONJOINT_OUT_REVERSE = 0x28,
|
||||
OP_CONJOINT_ATOP = 0x29,
|
||||
OP_CONJOINT_ATOP_REVERSE = 0x2a,
|
||||
OP_CONJOINT_XOR = 0x2b,
|
||||
OP_MULTIPLY = 0x30,
|
||||
OP_SCREEN = 0x31,
|
||||
OP_OVERLAY = 0x32,
|
||||
OP_DARKEN = 0x33,
|
||||
OP_LIGHTEN = 0x34,
|
||||
OP_COLOR_DODGE = 0x35,
|
||||
OP_COLOR_BURN = 0x36,
|
||||
OP_HARD_LIGHT = 0x37,
|
||||
OP_SOFT_LIGHT = 0x38,
|
||||
OP_DIFFERENCE = 0x39,
|
||||
OP_EXCLUSION = 0x3a,
|
||||
OP_HSL_HUE = 0x3b,
|
||||
OP_HSL_SATURATION = 0x3c,
|
||||
OP_HSL_COLOR = 0x3d,
|
||||
OP_HSL_LUMINOSITY = 0x3e,
|
||||
}
|
||||
19
src/rect.rs
19
src/rect.rs
|
|
@ -1,3 +1,10 @@
|
|||
mod region;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub use region::RegionBuilder;
|
||||
use smallvec::SmallVec;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Default)]
|
||||
|
|
@ -8,6 +15,14 @@ pub struct Rect {
|
|||
y2: i32,
|
||||
}
|
||||
|
||||
type Container = SmallVec<[Rect; 1]>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Region {
|
||||
rects: Container,
|
||||
extents: Rect,
|
||||
}
|
||||
|
||||
impl Debug for Rect {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Rect")
|
||||
|
|
@ -60,6 +75,10 @@ impl Rect {
|
|||
Some(Self { x1, y1, x2, y2 })
|
||||
}
|
||||
|
||||
fn new_unchecked(x1: i32, y1: i32, x2: i32, y2: i32) -> Self {
|
||||
Self { x1, y1, x2, y2 }
|
||||
}
|
||||
|
||||
pub fn new_sized(x1: i32, y1: i32, width: i32, height: i32) -> Option<Self> {
|
||||
if width < 0 || height < 0 {
|
||||
return None;
|
||||
|
|
|
|||
571
src/rect/region.rs
Normal file
571
src/rect/region.rs
Normal file
|
|
@ -0,0 +1,571 @@
|
|||
use crate::rect::{Container, Rect, Region};
|
||||
use crate::utils::windows::WindowsExt;
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BinaryHeap};
|
||||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
impl Region {
|
||||
pub fn new(rect: Rect) -> Self {
|
||||
let mut rects = SmallVec::new();
|
||||
rects.push(rect);
|
||||
Self {
|
||||
rects,
|
||||
extents: rect,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_rects(rects: &[Rect]) -> Self {
|
||||
if rects.is_empty() {
|
||||
return Self::default();
|
||||
}
|
||||
if rects.len() == 1 {
|
||||
return Self::new(rects[0]);
|
||||
}
|
||||
let rects = rects_to_bands(rects);
|
||||
Self {
|
||||
extents: extents(&rects),
|
||||
rects,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
let rects = op::<Union>(&self.rects, &other.rects);
|
||||
Self {
|
||||
rects,
|
||||
extents: self.extents.union(other.extents),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subtract(&self, other: &Self) -> Self {
|
||||
let rects = op::<Subtract>(&self.rects, &other.rects);
|
||||
Self {
|
||||
extents: extents(&rects),
|
||||
rects,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extents(&self) -> Rect {
|
||||
self.extents
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Region {
|
||||
type Target = [Rect];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.rects
|
||||
}
|
||||
}
|
||||
|
||||
struct Bands<'a> {
|
||||
rects: &'a [Rect],
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Band<'a> {
|
||||
rects: &'a [Rect],
|
||||
y1: i32,
|
||||
y2: i32,
|
||||
}
|
||||
|
||||
impl<'a> Band<'a> {
|
||||
fn can_merge_with(&self, next: &Band) -> bool {
|
||||
next.rects.len() == self.rects.len()
|
||||
&& next.y1 == self.y2
|
||||
&& next
|
||||
.rects
|
||||
.iter()
|
||||
.zip(self.rects.iter())
|
||||
.all(|(a, b)| (a.x1, a.x2) == (b.x1, b.x2))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Bands<'a> {
|
||||
type Item = Band<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.rects.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let y1 = self.rects[0].y1();
|
||||
let y2 = self.rects[0].y2();
|
||||
for (pos, rect) in self.rects[1..].iter().enumerate() {
|
||||
if rect.y1() != y1 {
|
||||
let (res, rects) = self.rects.split_at(pos + 1);
|
||||
self.rects = rects;
|
||||
return Some(Band { rects: res, y1, y2 });
|
||||
}
|
||||
}
|
||||
Some(Band {
|
||||
rects: mem::replace(&mut self.rects, &[]),
|
||||
y1,
|
||||
y2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn extents(a: &[Rect]) -> Rect {
|
||||
let mut a = a.iter();
|
||||
let mut res = match a.next() {
|
||||
Some(a) => *a,
|
||||
_ => return Rect::default(),
|
||||
};
|
||||
for a in a {
|
||||
res.x1 = res.x1.min(a.x1);
|
||||
res.y1 = res.y1.min(a.y1);
|
||||
res.x2 = res.x2.max(a.x2);
|
||||
res.y2 = res.y2.max(a.y2);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn op<O: Op>(a: &[Rect], b: &[Rect]) -> Container {
|
||||
let mut res = Container::new();
|
||||
|
||||
let mut prev_band_y2 = 0;
|
||||
let mut prev_band_start = 0;
|
||||
let mut cur_band_start;
|
||||
|
||||
let mut a_bands = Bands { rects: a };
|
||||
let mut b_bands = Bands { rects: b };
|
||||
|
||||
let mut a_opt = a_bands.next();
|
||||
let mut b_opt = b_bands.next();
|
||||
|
||||
macro_rules! fixup_new_band {
|
||||
($y1:expr, $y2:expr) => {{
|
||||
if prev_band_y2 != $y1 || !coalesce(&mut res, prev_band_start, cur_band_start, $y2) {
|
||||
prev_band_start = cur_band_start;
|
||||
}
|
||||
prev_band_y2 = $y2;
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! append_nonoverlapping {
|
||||
($append_opt:expr, $a:expr, $a_opt:expr, $a_bands:expr, $b:expr) => {{
|
||||
if $append_opt {
|
||||
let y2 = $a.y2.min($b.y1);
|
||||
cur_band_start = res.len();
|
||||
res.reserve($a.rects.len());
|
||||
for rect in $a.rects {
|
||||
res.push(Rect {
|
||||
x1: rect.x1,
|
||||
y1: $a.y1,
|
||||
x2: rect.x2,
|
||||
y2,
|
||||
});
|
||||
}
|
||||
fixup_new_band!($a.y1, y2);
|
||||
}
|
||||
if $a.y2 <= $b.y1 {
|
||||
$a_opt = $a_bands.next();
|
||||
} else {
|
||||
$a.y1 = $b.y1;
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
while let (Some(a), Some(b)) = (&mut a_opt, &mut b_opt) {
|
||||
if a.y1 < b.y1 {
|
||||
append_nonoverlapping!(O::APPEND_NON_A, a, a_opt, a_bands, b);
|
||||
} else if b.y1 < a.y1 {
|
||||
append_nonoverlapping!(O::APPEND_NON_B, b, b_opt, b_bands, a);
|
||||
} else {
|
||||
let y2 = a.y2.min(b.y2);
|
||||
cur_band_start = res.len();
|
||||
O::handle_band(&mut res, a.rects, b.rects, a.y1, y2);
|
||||
if res.len() > cur_band_start {
|
||||
fixup_new_band!(a.y1, y2);
|
||||
}
|
||||
if a.y2 == y2 {
|
||||
a_opt = a_bands.next();
|
||||
} else {
|
||||
a.y1 = y2;
|
||||
}
|
||||
if b.y2 == y2 {
|
||||
b_opt = b_bands.next();
|
||||
} else {
|
||||
b.y1 = y2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! push_trailing {
|
||||
($a_opt:expr, $a_bands:expr) => {{
|
||||
while let Some(a) = $a_opt {
|
||||
cur_band_start = res.len();
|
||||
res.reserve(a.rects.len());
|
||||
for rect in a.rects {
|
||||
res.push(Rect {
|
||||
x1: rect.x1,
|
||||
y1: a.y1,
|
||||
x2: rect.x2,
|
||||
y2: a.y2,
|
||||
});
|
||||
}
|
||||
fixup_new_band!(a.y1, a.y2);
|
||||
$a_opt = $a_bands.next();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
if O::APPEND_NON_A {
|
||||
push_trailing!(a_opt, a_bands);
|
||||
}
|
||||
|
||||
if O::APPEND_NON_B {
|
||||
push_trailing!(b_opt, b_bands);
|
||||
}
|
||||
|
||||
res.shrink_to_fit();
|
||||
res
|
||||
}
|
||||
|
||||
fn coalesce(new: &mut Container, a: usize, b: usize, y2: i32) -> bool {
|
||||
if new.len() - b != b - a {
|
||||
return false;
|
||||
}
|
||||
let slice_a = &new[a..b];
|
||||
let slice_b = &new[b..];
|
||||
for (a, b) in slice_a.iter().zip(slice_b.iter()) {
|
||||
if (a.x1(), a.x2()) != (b.x1(), b.x2()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for rect in &mut new[a..b] {
|
||||
rect.y2 = y2;
|
||||
}
|
||||
new.truncate(b);
|
||||
true
|
||||
}
|
||||
|
||||
trait Op {
|
||||
const APPEND_NON_A: bool;
|
||||
const APPEND_NON_B: bool;
|
||||
|
||||
fn handle_band(new: &mut Container, a: &[Rect], b: &[Rect], y1: i32, y2: i32);
|
||||
}
|
||||
|
||||
struct Union;
|
||||
|
||||
impl Op for Union {
|
||||
const APPEND_NON_A: bool = true;
|
||||
const APPEND_NON_B: bool = true;
|
||||
|
||||
fn handle_band(new: &mut Container, mut a: &[Rect], mut b: &[Rect], y1: i32, y2: i32) {
|
||||
let mut x1;
|
||||
let mut x2;
|
||||
|
||||
macro_rules! push {
|
||||
() => {
|
||||
new.push(Rect { x1, y1, x2, y2 });
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! merge {
|
||||
($r:expr) => {
|
||||
if $r.x1 <= x2 {
|
||||
if $r.x2 > x2 {
|
||||
x2 = $r.x2;
|
||||
}
|
||||
} else {
|
||||
push!();
|
||||
x1 = $r.x1;
|
||||
x2 = $r.x2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if a[0].x1 < b[0].x1 {
|
||||
x1 = a[0].x1;
|
||||
x2 = a[0].x2;
|
||||
a = &a[1..];
|
||||
} else {
|
||||
x1 = b[0].x1;
|
||||
x2 = b[0].x2;
|
||||
b = &b[1..];
|
||||
}
|
||||
|
||||
let mut a_iter = a.iter();
|
||||
let mut b_iter = b.iter();
|
||||
|
||||
let mut a_opt = a_iter.next();
|
||||
let mut b_opt = b_iter.next();
|
||||
|
||||
while let (Some(a), Some(b)) = (a_opt, b_opt) {
|
||||
if a.x1 < b.x1 {
|
||||
merge!(a);
|
||||
a_opt = a_iter.next();
|
||||
} else {
|
||||
merge!(b);
|
||||
b_opt = b_iter.next();
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(a) = a_opt {
|
||||
merge!(a);
|
||||
a_opt = a_iter.next();
|
||||
}
|
||||
|
||||
while let Some(b) = b_opt {
|
||||
merge!(b);
|
||||
b_opt = b_iter.next();
|
||||
}
|
||||
|
||||
push!();
|
||||
}
|
||||
}
|
||||
|
||||
struct Subtract;
|
||||
|
||||
impl Op for Subtract {
|
||||
const APPEND_NON_A: bool = true;
|
||||
const APPEND_NON_B: bool = false;
|
||||
|
||||
fn handle_band(new: &mut Container, a: &[Rect], b: &[Rect], y1: i32, y2: i32) {
|
||||
let mut x1;
|
||||
let mut x2;
|
||||
|
||||
macro_rules! push {
|
||||
($x2:expr) => {
|
||||
new.push(Rect {
|
||||
x1,
|
||||
y1,
|
||||
x2: $x2,
|
||||
y2,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
let mut a_iter = a.iter();
|
||||
let mut b_iter = b.iter();
|
||||
|
||||
macro_rules! pull {
|
||||
() => {
|
||||
match a_iter.next() {
|
||||
Some(n) => {
|
||||
x1 = n.x1;
|
||||
x2 = n.x2;
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pull!();
|
||||
|
||||
let mut b_opt = b_iter.next();
|
||||
|
||||
while let Some(b) = b_opt {
|
||||
if b.x2 <= x1 {
|
||||
b_opt = b_iter.next();
|
||||
} else if b.x1 >= x2 {
|
||||
push!(x2);
|
||||
pull!();
|
||||
} else {
|
||||
if b.x1 > x1 {
|
||||
push!(b.x1);
|
||||
}
|
||||
if b.x2 < x2 {
|
||||
x1 = b.x2;
|
||||
} else {
|
||||
pull!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
push!(x2);
|
||||
pull!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rects_to_bands(rects_tmp: &[Rect]) -> Container {
|
||||
#[derive(Copy, Clone)]
|
||||
struct W(Rect);
|
||||
impl Eq for W {}
|
||||
impl PartialEq<Self> for W {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Self> for W {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl Ord for W {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.0
|
||||
.y1
|
||||
.cmp(&other.0.y1)
|
||||
.then_with(|| self.0.x1.cmp(&other.0.x1))
|
||||
.reverse()
|
||||
}
|
||||
}
|
||||
impl Deref for W {
|
||||
type Target = Rect;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
let ys = {
|
||||
let mut tmp: Vec<_> = rects_tmp.iter().flat_map(|r| [r.y1, r.y2]).collect();
|
||||
tmp.sort_unstable();
|
||||
let mut last = None;
|
||||
let mut res = vec![];
|
||||
for y in tmp {
|
||||
if Some(y) != last {
|
||||
last = Some(y);
|
||||
res.push(y);
|
||||
}
|
||||
}
|
||||
res
|
||||
};
|
||||
|
||||
let mut rects = BinaryHeap::with_capacity(rects_tmp.len());
|
||||
for rect in rects_tmp.iter().copied() {
|
||||
if !rect.is_empty() {
|
||||
rects.push(W(rect));
|
||||
}
|
||||
}
|
||||
|
||||
let mut res = Container::new();
|
||||
|
||||
for &[y1, y2] in ys.array_windows_ext::<2>() {
|
||||
loop {
|
||||
macro_rules! check_rect {
|
||||
($rect:expr) => {{
|
||||
if $rect.y1 != y1 {
|
||||
break;
|
||||
}
|
||||
rects.pop();
|
||||
if y2 < $rect.y2 {
|
||||
$rect.0.y1 = y2;
|
||||
rects.push($rect);
|
||||
}
|
||||
}};
|
||||
}
|
||||
if let Some(mut rect) = rects.peek().copied() {
|
||||
check_rect!(rect);
|
||||
let mut x1 = rect.x1;
|
||||
let mut x2 = rect.x2;
|
||||
while let Some(mut rect) = rects.peek().copied() {
|
||||
check_rect!(rect);
|
||||
if rect.x1 > x2 {
|
||||
res.push(Rect { x1, x2, y1, y2 });
|
||||
x1 = rect.x1;
|
||||
x2 = rect.x2;
|
||||
} else {
|
||||
x2 = x2.max(rect.x2);
|
||||
}
|
||||
}
|
||||
res.push(Rect { x1, x2, y1, y2 });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let mut needs_merge = false;
|
||||
let mut num_elements = res.len();
|
||||
let mut bands = Bands { rects: &res }.peekable();
|
||||
while let Some(band) = bands.next() {
|
||||
let next = match bands.peek() {
|
||||
Some(next) => next,
|
||||
_ => break,
|
||||
};
|
||||
if band.can_merge_with(next) {
|
||||
needs_merge = true;
|
||||
num_elements -= band.rects.len();
|
||||
}
|
||||
}
|
||||
|
||||
if !needs_merge {
|
||||
res.shrink_to_fit();
|
||||
return res;
|
||||
}
|
||||
|
||||
let mut merged = Container::with_capacity(num_elements);
|
||||
let mut bands = Bands { rects: &res }.peekable();
|
||||
while let Some(mut band) = bands.next() {
|
||||
while let Some(next) = bands.peek() {
|
||||
if band.can_merge_with(next) {
|
||||
band.y2 = next.y2;
|
||||
bands.next();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for mut rect in band.rects.iter().copied() {
|
||||
rect.y2 = band.y2;
|
||||
merged.push(rect);
|
||||
}
|
||||
}
|
||||
|
||||
merged
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
enum BuilderOp {
|
||||
Add,
|
||||
Sub,
|
||||
}
|
||||
|
||||
impl Default for BuilderOp {
|
||||
fn default() -> Self {
|
||||
Self::Add
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RegionBuilder {
|
||||
base: Rc<Region>,
|
||||
op: BuilderOp,
|
||||
pending: Vec<Rect>,
|
||||
}
|
||||
|
||||
impl RegionBuilder {
|
||||
pub fn add(&mut self, rect: Rect) {
|
||||
self.set_op(BuilderOp::Add);
|
||||
self.pending.push(rect);
|
||||
}
|
||||
|
||||
pub fn sub(&mut self, rect: Rect) {
|
||||
self.set_op(BuilderOp::Sub);
|
||||
self.pending.push(rect);
|
||||
}
|
||||
|
||||
pub fn get(&mut self) -> Rc<Region> {
|
||||
self.flush();
|
||||
self.base.clone()
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.pending.clear();
|
||||
self.base = Rc::new(Region::default());
|
||||
}
|
||||
|
||||
fn set_op(&mut self, op: BuilderOp) {
|
||||
if self.op != op {
|
||||
self.flush();
|
||||
self.op = op;
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self) {
|
||||
if self.pending.is_empty() {
|
||||
return;
|
||||
}
|
||||
let region = Region::from_rects(&self.pending);
|
||||
let base = match self.op {
|
||||
BuilderOp::Add => self.base.union(®ion),
|
||||
BuilderOp::Sub => self.base.subtract(®ion),
|
||||
};
|
||||
self.base = Rc::new(base);
|
||||
}
|
||||
}
|
||||
60
src/rect/tests.rs
Normal file
60
src/rect/tests.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use crate::rect::{Rect, Region};
|
||||
|
||||
#[test]
|
||||
fn union1() {
|
||||
let r1 = Region::new(Rect::new(0, 0, 10, 10).unwrap());
|
||||
let r2_ = Region::new(Rect::new(5, 5, 15, 15).unwrap());
|
||||
let r2 = Region::new(Rect::new(10, 10, 20, 20).unwrap());
|
||||
let r3 = r1.union(&r2).union(&r2_);
|
||||
assert_eq!(r3.extents, Rect::new(0, 0, 20, 20).unwrap());
|
||||
assert_eq!(
|
||||
&r3.rects[..],
|
||||
&[
|
||||
Rect::new(0, 0, 10, 5).unwrap(),
|
||||
Rect::new(0, 5, 15, 10).unwrap(),
|
||||
Rect::new(5, 10, 20, 15).unwrap(),
|
||||
Rect::new(10, 15, 20, 20).unwrap(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn union2() {
|
||||
let r1 = Region::new(Rect::new(0, 0, 10, 10).unwrap());
|
||||
let r2 = Region::new(Rect::new(0, 10, 10, 20).unwrap());
|
||||
let r3 = r1.union(&r2);
|
||||
assert_eq!(r3.extents, Rect::new(0, 0, 10, 20).unwrap());
|
||||
assert_eq!(&r3.rects[..], &[Rect::new(0, 0, 10, 20).unwrap(),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtract1() {
|
||||
let r1 = Region::new(Rect::new(0, 0, 20, 20).unwrap());
|
||||
let r2 = Region::new(Rect::new(5, 5, 15, 15).unwrap());
|
||||
let r3 = r1.subtract(&r2);
|
||||
assert_eq!(r3.extents, Rect::new(0, 0, 20, 20).unwrap());
|
||||
assert_eq!(&r3.rects[..], &[Rect::new(0, 0, 10, 20).unwrap(),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rects_to_bands() {
|
||||
let rects = [
|
||||
Rect::new_unchecked(0, 0, 10, 10),
|
||||
Rect::new_unchecked(5, 0, 30, 10),
|
||||
Rect::new_unchecked(30, 5, 50, 15),
|
||||
];
|
||||
let r = Region::from_rects(&rects[..]);
|
||||
println!("{:#?}", r.rects);
|
||||
assert_eq!(&r.rects[..], &[Rect::new(0, 0, 10, 20).unwrap(),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rects_to_bands2() {
|
||||
let rects = [
|
||||
Rect::new_unchecked(0, 0, 10, 10),
|
||||
Rect::new_unchecked(0, 10, 10, 20),
|
||||
];
|
||||
let r = Region::from_rects(&rects[..]);
|
||||
println!("{:#?}", r.rects);
|
||||
assert_eq!(&r.rects[..], &[Rect::new(0, 0, 10, 20).unwrap(),]);
|
||||
}
|
||||
|
|
@ -19,9 +19,9 @@ macro_rules! egl_transparent {
|
|||
}
|
||||
|
||||
use crate::drm::drm::DrmError;
|
||||
use crate::drm::gbm::GbmError;
|
||||
pub use renderer::*;
|
||||
use thiserror::Error;
|
||||
use crate::drm::gbm::GbmError;
|
||||
|
||||
mod egl;
|
||||
mod ext;
|
||||
|
|
@ -48,16 +48,10 @@ pub enum RenderError {
|
|||
ProgramLink,
|
||||
#[error("Could not bind to `EGL_OPENGL_ES_API`")]
|
||||
BindFailed,
|
||||
#[error("EGL library does not support device enumeration")]
|
||||
DeviceEnumeration,
|
||||
#[error("EGL library does not support the GBM platform")]
|
||||
GbmExt,
|
||||
#[error("Could not create a GBM device")]
|
||||
Gbm(#[source] GbmError),
|
||||
#[error("EGL library does not support device querying")]
|
||||
DeviceQuery,
|
||||
#[error("`eglQueryDeviceStringEXT` failed")]
|
||||
DeviceQueryString,
|
||||
#[error("`eglCreateContext` failed")]
|
||||
CreateContext,
|
||||
#[error("`eglMakeCurrent` failed")]
|
||||
|
|
@ -68,8 +62,6 @@ pub enum RenderError {
|
|||
SmallImageBuffer,
|
||||
#[error("Binding a renderbuffer to a framebuffer failed")]
|
||||
CreateFramebuffer,
|
||||
#[error("`eglQueryDevicesEXT` failed")]
|
||||
QueryDevices,
|
||||
#[error("`eglGetPlatformDisplayEXT` failed")]
|
||||
GetDisplay,
|
||||
#[error("`eglInitialize` failed")]
|
||||
|
|
@ -90,8 +82,6 @@ pub enum RenderError {
|
|||
QueryDmaBufFormats,
|
||||
#[error(transparent)]
|
||||
DrmError(#[from] DrmError),
|
||||
#[error("Could not find the requested DRM device")]
|
||||
UnknownDrmDevice,
|
||||
#[error("The GLES driver does not support the XRGB8888 format")]
|
||||
XRGB888,
|
||||
#[error("The DRM device does not have a render node")]
|
||||
|
|
|
|||
|
|
@ -1,19 +1,15 @@
|
|||
use crate::drm::drm::NodeType;
|
||||
use crate::render::egl::device::EglDevice;
|
||||
use crate::render::egl::sys::{
|
||||
eglBindAPI, EGLAttrib, EGLLabelKHR, EGLenum, EGLint, EGL_DEBUG_MSG_CRITICAL_KHR,
|
||||
EGL_DEBUG_MSG_ERROR_KHR, EGL_DEBUG_MSG_INFO_KHR, EGL_DEBUG_MSG_WARN_KHR,
|
||||
EGL_DRM_DEVICE_FILE_EXT, EGL_NONE, EGL_OPENGL_ES_API, EGL_TRUE,
|
||||
EGL_DEBUG_MSG_ERROR_KHR, EGL_DEBUG_MSG_INFO_KHR, EGL_DEBUG_MSG_WARN_KHR, EGL_NONE,
|
||||
EGL_OPENGL_ES_API, EGL_TRUE,
|
||||
};
|
||||
use crate::render::ext::{get_client_ext, get_device_ext, ClientExt, DeviceExt};
|
||||
use crate::render::ext::{get_client_ext, ClientExt};
|
||||
use crate::render::proc::ExtProc;
|
||||
use crate::render::RenderError;
|
||||
use ahash::AHashMap;
|
||||
use bstr::ByteSlice;
|
||||
use log::Level;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr;
|
||||
use std::ffi::CStr;
|
||||
use sys::{
|
||||
EGL_BAD_ACCESS, EGL_BAD_ALLOC, EGL_BAD_ATTRIBUTE, EGL_BAD_CONFIG, EGL_BAD_CONTEXT,
|
||||
EGL_BAD_CURRENT_SURFACE, EGL_BAD_DEVICE_EXT, EGL_BAD_DISPLAY, EGL_BAD_MATCH,
|
||||
|
|
@ -23,7 +19,6 @@ use sys::{
|
|||
use uapi::c;
|
||||
|
||||
pub mod context;
|
||||
pub mod device;
|
||||
pub mod display;
|
||||
pub mod image;
|
||||
pub mod sys;
|
||||
|
|
@ -36,14 +31,8 @@ pub fn init() -> Result<(), RenderError> {
|
|||
if !EXTS.contains(ClientExt::EXT_PLATFORM_BASE) {
|
||||
return Err(RenderError::ExtPlatformBase);
|
||||
}
|
||||
if !EXTS.device_query() {
|
||||
return Err(RenderError::DeviceQuery);
|
||||
}
|
||||
if !EXTS.device_enumeration() {
|
||||
return Err(RenderError::DeviceEnumeration);
|
||||
}
|
||||
if !EXTS.platform_gbm() {
|
||||
return Err(RenderError::DeviceEnumeration);
|
||||
if !EXTS.contains(ClientExt::KHR_PLATFORM_GBM) {
|
||||
return Err(RenderError::GbmExt);
|
||||
}
|
||||
if EXTS.contains(ClientExt::KHR_DEBUG) {
|
||||
let attrib: &[EGLAttrib] = &[
|
||||
|
|
@ -67,49 +56,6 @@ pub fn init() -> Result<(), RenderError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn find_drm_device(
|
||||
drm_dev: &AHashMap<NodeType, CString>,
|
||||
) -> Result<Option<EglDevice>, RenderError> {
|
||||
for device in query_devices()? {
|
||||
if device.exts.contains(DeviceExt::EXT_DEVICE_DRM) {
|
||||
let device_file = device.query_string(EGL_DRM_DEVICE_FILE_EXT)?;
|
||||
for name in drm_dev.values() {
|
||||
if device_file == &**name {
|
||||
return Ok(Some(device));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn query_devices() -> Result<Vec<EglDevice>, RenderError> {
|
||||
if !EXTS.device_enumeration() {
|
||||
return Err(RenderError::DeviceEnumeration);
|
||||
}
|
||||
unsafe {
|
||||
let mut devices = vec![];
|
||||
let mut num_devices = 0;
|
||||
let res = PROCS.eglQueryDevicesEXT(num_devices, ptr::null_mut(), &mut num_devices);
|
||||
if res != EGL_TRUE {
|
||||
return Err(RenderError::QueryDevices);
|
||||
}
|
||||
devices.reserve_exact(num_devices as usize);
|
||||
let res = PROCS.eglQueryDevicesEXT(num_devices, devices.as_mut_ptr(), &mut num_devices);
|
||||
if res != EGL_TRUE {
|
||||
return Err(RenderError::QueryDevices);
|
||||
}
|
||||
devices.set_len(num_devices as usize);
|
||||
Ok(devices
|
||||
.into_iter()
|
||||
.map(|d| EglDevice {
|
||||
exts: get_device_ext(d),
|
||||
dev: d,
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn egl_log(
|
||||
error: EGLenum,
|
||||
command: *const c::c_char,
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
use crate::format::{formats, Format};
|
||||
use crate::render::egl::display::EglDisplay;
|
||||
use crate::render::egl::sys::{
|
||||
eglInitialize, EGLDeviceEXT, EGLDisplay, EGLint, EGL_PLATFORM_DEVICE_EXT, EGL_TRUE,
|
||||
};
|
||||
use crate::render::egl::PROCS;
|
||||
use crate::render::ext::{get_display_ext, DeviceExt, DisplayExt};
|
||||
use crate::render::RenderError;
|
||||
use ahash::AHashMap;
|
||||
use std::ffi::CStr;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct EglDevice {
|
||||
pub exts: DeviceExt,
|
||||
pub dev: EGLDeviceEXT,
|
||||
}
|
||||
|
||||
impl EglDevice {
|
||||
pub fn query_string(&self, name: EGLint) -> Result<&'static CStr, RenderError> {
|
||||
unsafe {
|
||||
let res = PROCS.eglQueryDeviceStringEXT(self.dev, name);
|
||||
if res.is_null() {
|
||||
return Err(RenderError::DeviceQueryString);
|
||||
}
|
||||
Ok(CStr::from_ptr(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_display(&self) -> Result<Rc<EglDisplay>, RenderError> {
|
||||
unsafe {
|
||||
let dpy = PROCS.eglGetPlatformDisplayEXT(
|
||||
EGL_PLATFORM_DEVICE_EXT as _,
|
||||
self.dev.0,
|
||||
ptr::null(),
|
||||
);
|
||||
if dpy.is_none() {
|
||||
return Err(RenderError::GetDisplay);
|
||||
}
|
||||
let mut dpy = EglDisplay {
|
||||
exts: DisplayExt::empty(),
|
||||
formats: Rc::new(AHashMap::new()),
|
||||
dev: Some(*self),
|
||||
gbm: None,
|
||||
dpy,
|
||||
};
|
||||
let mut major = 0;
|
||||
let mut minor = 0;
|
||||
if eglInitialize(dpy.dpy, &mut major, &mut minor) != EGL_TRUE {
|
||||
return Err(RenderError::Initialize);
|
||||
}
|
||||
dpy.exts = get_display_ext(dpy.dpy);
|
||||
if !dpy.exts.intersects(DisplayExt::KHR_IMAGE_BASE) {
|
||||
return Err(RenderError::ImageBase);
|
||||
}
|
||||
if !dpy
|
||||
.exts
|
||||
.intersects(DisplayExt::EXT_IMAGE_DMA_BUF_IMPORT_MODIFIERS)
|
||||
{
|
||||
return Err(RenderError::DmaBufImport);
|
||||
}
|
||||
if !dpy
|
||||
.exts
|
||||
.intersects(DisplayExt::KHR_NO_CONFIG_CONTEXT | DisplayExt::MESA_CONFIGLESS_CONTEXT)
|
||||
{
|
||||
return Err(RenderError::ConfiglessContext);
|
||||
}
|
||||
if !dpy.exts.intersects(DisplayExt::KHR_SURFACELESS_CONTEXT) {
|
||||
return Err(RenderError::SurfacelessContext);
|
||||
}
|
||||
dpy.formats = Rc::new(query_formats(dpy.dpy)?);
|
||||
|
||||
Ok(Rc::new(dpy))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, &'static Format>, RenderError> {
|
||||
let mut vec = vec![];
|
||||
let mut num = 0;
|
||||
let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num);
|
||||
if res != EGL_TRUE {
|
||||
return Err(RenderError::QueryDmaBufFormats);
|
||||
}
|
||||
vec.reserve_exact(num as usize);
|
||||
let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, vec.as_mut_ptr(), &mut num);
|
||||
if res != EGL_TRUE {
|
||||
return Err(RenderError::QueryDmaBufFormats);
|
||||
}
|
||||
vec.set_len(num as usize);
|
||||
let mut res = AHashMap::new();
|
||||
let formats = formats();
|
||||
for fmt in vec {
|
||||
if let Some(format) = formats.get(&(fmt as u32)) {
|
||||
res.insert(format.drm, *format);
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
use std::ptr;
|
||||
use crate::drm::dma::DmaBuf;
|
||||
use crate::drm::drm::Drm;
|
||||
use crate::drm::gbm::GbmDevice;
|
||||
use crate::drm::INVALID_MODIFIER;
|
||||
use crate::format::{Format, formats};
|
||||
use crate::format::{formats, Format};
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::egl::device::EglDevice;
|
||||
use crate::render::egl::image::EglImage;
|
||||
use crate::render::egl::sys::{
|
||||
eglCreateContext, eglTerminate, EGLClientBuffer, EGLConfig, EGLContext, EGLDisplay, EGLint,
|
||||
|
|
@ -19,20 +19,18 @@ use crate::render::egl::sys::{
|
|||
EGL_LINUX_DRM_FOURCC_EXT, EGL_NONE, EGL_TRUE, EGL_WIDTH,
|
||||
};
|
||||
use crate::render::egl::PROCS;
|
||||
use crate::render::ext::{get_gl_ext, DisplayExt, GlExt, get_display_ext};
|
||||
use crate::render::ext::{get_display_ext, get_gl_ext, DisplayExt, GlExt};
|
||||
use crate::render::sys::{eglInitialize, EGL_PLATFORM_GBM_KHR};
|
||||
use crate::render::RenderError;
|
||||
use ahash::AHashMap;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use crate::drm::drm::Drm;
|
||||
use crate::drm::gbm::GbmDevice;
|
||||
use crate::render::sys::{EGL_PLATFORM_GBM_KHR, eglInitialize};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EglDisplay {
|
||||
pub exts: DisplayExt,
|
||||
pub formats: Rc<AHashMap<u32, &'static Format>>,
|
||||
pub dev: Option<EglDevice>,
|
||||
pub gbm: Option<GbmDevice>,
|
||||
pub gbm: GbmDevice,
|
||||
pub dpy: EGLDisplay,
|
||||
}
|
||||
|
||||
|
|
@ -54,8 +52,7 @@ impl EglDisplay {
|
|||
let mut dpy = EglDisplay {
|
||||
exts: DisplayExt::empty(),
|
||||
formats: Rc::new(AHashMap::new()),
|
||||
dev: None,
|
||||
gbm: Some(gbm),
|
||||
gbm,
|
||||
dpy,
|
||||
};
|
||||
let mut major = 0;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ egl_transparent!(EGLImageKHR);
|
|||
egl_transparent!(EGLContext);
|
||||
egl_transparent!(EGLClientBuffer);
|
||||
egl_transparent!(EGLLabelKHR);
|
||||
egl_transparent!(EGLDeviceEXT);
|
||||
|
||||
pub type EGLDEBUGPROCKHR = unsafe extern "C" fn(
|
||||
error: EGLenum,
|
||||
|
|
@ -50,8 +49,6 @@ pub const EGL_BAD_SURFACE: EGLint = 0x300D;
|
|||
pub const EGL_CONTEXT_LOST: EGLint = 0x300E;
|
||||
pub const EGL_BAD_DEVICE_EXT: EGLint = 0x322B;
|
||||
pub const EGL_OPENGL_ES_API: EGLenum = 0x30A0;
|
||||
pub const EGL_DRM_DEVICE_FILE_EXT: EGLint = 0x3233;
|
||||
pub const EGL_PLATFORM_DEVICE_EXT: EGLint = 0x313F;
|
||||
pub const EGL_PLATFORM_GBM_KHR: EGLint = 0x31D7;
|
||||
pub const EGL_CONTEXT_CLIENT_VERSION: EGLint = 0x3098;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
use crate::render::egl::sys::{eglQueryString, EGLDeviceEXT, EGLDisplay, EGL_EXTENSIONS};
|
||||
use crate::render::egl::PROCS;
|
||||
use crate::render::egl::sys::{eglQueryString, EGLDisplay, EGL_EXTENSIONS};
|
||||
use crate::render::gl::sys::{glGetString, GL_EXTENSIONS};
|
||||
use crate::utils::trim::AsciiTrim;
|
||||
use ahash::AHashSet;
|
||||
|
|
@ -48,25 +47,7 @@ bitflags::bitflags! {
|
|||
const EXT_CLIENT_EXTENSION = 1 << 0;
|
||||
const EXT_PLATFORM_BASE = 1 << 1;
|
||||
const KHR_PLATFORM_GBM = 1 << 2;
|
||||
const EXT_PLATFORM_DEVICE = 1 << 3;
|
||||
const EXT_DEVICE_BASE = 1 << 4;
|
||||
const EXT_DEVICE_ENUMERATION = 1 << 5;
|
||||
const EXT_DEVICE_QUERY = 1 << 6;
|
||||
const KHR_DEBUG = 1 << 7;
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientExt {
|
||||
pub fn device_enumeration(self) -> bool {
|
||||
self.contains(Self::EXT_DEVICE_BASE | Self::EXT_DEVICE_ENUMERATION)
|
||||
}
|
||||
|
||||
pub fn device_query(self) -> bool {
|
||||
self.contains(Self::EXT_DEVICE_BASE | Self::EXT_DEVICE_QUERY)
|
||||
}
|
||||
|
||||
pub fn platform_gbm(self) -> bool {
|
||||
self.contains(Self::KHR_PLATFORM_GBM)
|
||||
const KHR_DEBUG = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,13 +55,6 @@ pub fn get_client_ext() -> ClientExt {
|
|||
let map = [
|
||||
("EGL_EXT_platform_base", ClientExt::EXT_PLATFORM_BASE),
|
||||
("EGL_KHR_platform_gbm", ClientExt::KHR_PLATFORM_GBM),
|
||||
("EGL_EXT_platform_device", ClientExt::EXT_PLATFORM_DEVICE),
|
||||
("EGL_EXT_device_base", ClientExt::EXT_DEVICE_BASE),
|
||||
(
|
||||
"EGL_EXT_device_enumeration",
|
||||
ClientExt::EXT_DEVICE_ENUMERATION,
|
||||
),
|
||||
("EGL_EXT_device_query", ClientExt::EXT_DEVICE_QUERY),
|
||||
("EGL_KHR_debug", ClientExt::KHR_DEBUG),
|
||||
];
|
||||
match unsafe { get_dpy_extensions(EGLDisplay::none()) } {
|
||||
|
|
@ -132,35 +106,6 @@ pub(super) unsafe fn get_display_ext(dpy: EGLDisplay) -> DisplayExt {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
pub struct DeviceExt: u32 {
|
||||
const MESA_DEVICE_SOFTWARE = 1 << 0;
|
||||
const EXT_DEVICE_PERSISTENT_ID = 1 << 1;
|
||||
const EXT_DEVICE_DRM = 1 << 2;
|
||||
const EXT_DEVICE_DRM_RENDER_NODE = 1 << 3;
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn get_device_ext(dev: EGLDeviceEXT) -> DeviceExt {
|
||||
let map = [
|
||||
("EGL_MESA_device_software", DeviceExt::MESA_DEVICE_SOFTWARE),
|
||||
(
|
||||
"EGL_EXT_device_persistent_id",
|
||||
DeviceExt::EXT_DEVICE_PERSISTENT_ID,
|
||||
),
|
||||
("EGL_EXT_device_drm", DeviceExt::EXT_DEVICE_DRM),
|
||||
(
|
||||
"EGL_EXT_device_drm_render_node",
|
||||
DeviceExt::EXT_DEVICE_DRM_RENDER_NODE,
|
||||
),
|
||||
];
|
||||
let ext = PROCS.eglQueryDeviceStringEXT(dev, EGL_EXTENSIONS);
|
||||
match get_extensions(ext) {
|
||||
Some(exts) => get_typed_ext(&exts, DeviceExt::empty(), &map),
|
||||
_ => DeviceExt::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
pub struct GlExt: u32 {
|
||||
const GL_OES_EGL_IMAGE = 1 << 0;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::drm::dma::DmaBuf;
|
|||
use crate::drm::drm::{Drm, NodeType};
|
||||
use crate::format::{Format, XRGB8888};
|
||||
use crate::render::egl::context::EglContext;
|
||||
use crate::render::egl::find_drm_device;
|
||||
use crate::render::egl::display::EglDisplay;
|
||||
use crate::render::gl::program::GlProgram;
|
||||
use crate::render::gl::render_buffer::GlRenderBuffer;
|
||||
use crate::render::gl::sys::GLint;
|
||||
|
|
@ -16,7 +16,6 @@ use std::ffi::CString;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use uapi::ustr;
|
||||
use crate::render::egl::display::EglDisplay;
|
||||
|
||||
pub(super) struct TexProg {
|
||||
pub(super) prog: GlProgram,
|
||||
|
|
|
|||
|
|
@ -26,3 +26,4 @@ pub mod trim;
|
|||
pub mod vasprintf;
|
||||
pub mod vec_ext;
|
||||
pub mod vecstorage;
|
||||
pub mod windows;
|
||||
|
|
|
|||
40
src/utils/windows.rs
Normal file
40
src/utils/windows.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use crate::utils::ptr_ext::PtrExt;
|
||||
|
||||
pub trait WindowsExt<T> {
|
||||
type Windows<'a, const N: usize>: Iterator<Item = &'a [T; N]>
|
||||
where
|
||||
Self: 'a,
|
||||
T: 'a;
|
||||
|
||||
fn array_windows_ext<'a, const N: usize>(&'a self) -> Self::Windows<'a, N>;
|
||||
}
|
||||
|
||||
impl<T> WindowsExt<T> for [T] {
|
||||
type Windows<'a, const N: usize>
|
||||
where
|
||||
T: 'a,
|
||||
= WindowsIter<'a, T, N>;
|
||||
|
||||
fn array_windows_ext<'a, const N: usize>(&'a self) -> Self::Windows<'a, N> {
|
||||
WindowsIter { slice: self }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowsIter<'a, T, const N: usize> {
|
||||
slice: &'a [T],
|
||||
}
|
||||
|
||||
impl<'a, T, const N: usize> Iterator for WindowsIter<'a, T, N> {
|
||||
type Item = &'a [T; N];
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.slice.len() < N {
|
||||
return None;
|
||||
}
|
||||
let res = unsafe { self.slice.as_ptr().cast::<[T; N]>().deref() };
|
||||
if N > 0 {
|
||||
self.slice = &self.slice[1..];
|
||||
}
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue