autocommit 2022-01-06 19:08:32 CET
This commit is contained in:
parent
cbbc41a463
commit
4a939477a2
51 changed files with 3438 additions and 207 deletions
192
src/pixman/consts.rs
Normal file
192
src/pixman/consts.rs
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
pub const fn format(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> u32 {
|
||||
(bpp << 24) | (ty << 16) | (a << 12) | (r << 8) | (g << 4) | b
|
||||
}
|
||||
|
||||
pub const fn format_byte(bpp: u32, ty: u32, a: u32, r: u32, g: u32, b: u32) -> u32 {
|
||||
((bpp >> 3) << 24)
|
||||
| (3 << 22)
|
||||
| (ty << 16)
|
||||
| ((a >> 3) << 12)
|
||||
| ((r >> 3) << 8)
|
||||
| ((g >> 3) << 4)
|
||||
| (b >> 3)
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
291
src/pixman/mod.rs
Normal file
291
src/pixman/mod.rs
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
mod consts;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/pixman_tys.rs"));
|
||||
|
||||
use crate::ClientMemError;
|
||||
pub use consts::*;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use thiserror::Error;
|
||||
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);
|
||||
fn pixman_image_create_bits_no_clear(
|
||||
format: PixmanFormat,
|
||||
width: c::c_int,
|
||||
height: c::c_int,
|
||||
bits: *mut u32,
|
||||
stride: c::c_int,
|
||||
) -> *mut PixmanImage;
|
||||
fn pixman_image_unref(image: *mut PixmanImage) -> c::c_int;
|
||||
// fn pixman_image_ref(image: *mut PixmanImage) -> *mut PixmanImage;
|
||||
fn pixman_image_fill_boxes(
|
||||
op: PixmanOp,
|
||||
dest: *mut PixmanImage,
|
||||
color: *const Color,
|
||||
nboxes: c::c_int,
|
||||
boxes: *const Box32,
|
||||
) -> c::c_int;
|
||||
fn pixman_image_composite32(
|
||||
op: PixmanOp,
|
||||
src: *mut PixmanImage,
|
||||
mask: *mut PixmanImage,
|
||||
dest: *mut PixmanImage,
|
||||
src_x: i32,
|
||||
src_y: i32,
|
||||
mask_x: i32,
|
||||
mask_y: i32,
|
||||
dest_x: i32,
|
||||
dest_y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
);
|
||||
}
|
||||
|
||||
#[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: u32, height: u32) -> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe trait PixmanMemory: Clone {
|
||||
type E;
|
||||
|
||||
fn access<T, F>(&self, f: F) -> Result<T, Self::E>
|
||||
where
|
||||
F: FnOnce(&[Cell<u8>]) -> T;
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PixmanError {
|
||||
#[error("The image size values cannot be represented in c_int")]
|
||||
SizeOverflow,
|
||||
#[error("The pixman memory does not contain enough memory to hold the image")]
|
||||
InsufficientMemory,
|
||||
#[error("The stride does not contain enough bytes to contain a row")]
|
||||
RowOverflow,
|
||||
#[error("Pixman images must be aligned at a 4 byte boundary")]
|
||||
UnalignedMemory,
|
||||
#[error("Internal pixman error")]
|
||||
Internal,
|
||||
#[error(transparent)]
|
||||
ClientMemError(Box<ClientMemError>),
|
||||
}
|
||||
efrom!(PixmanError, ClientMemError, ClientMemError);
|
||||
|
||||
impl From<!> for PixmanError {
|
||||
fn from(_: !) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
struct PixmanImage;
|
||||
|
||||
pub struct Image<T> {
|
||||
data: *mut PixmanImage,
|
||||
width: u32,
|
||||
height: u32,
|
||||
memory: T,
|
||||
}
|
||||
|
||||
impl<T: PixmanMemory> Image<T>
|
||||
where
|
||||
PixmanError: From<<T as PixmanMemory>::E>,
|
||||
{
|
||||
pub fn new(
|
||||
memory: T,
|
||||
format: Format,
|
||||
width: u32,
|
||||
height: u32,
|
||||
stride: u32,
|
||||
) -> Result<Self, PixmanError> {
|
||||
let data = memory.access(|m| {
|
||||
if format_bpp(format.raw()) as u64 * width as u64 > stride as u64 * 8 {
|
||||
return Err(PixmanError::RowOverflow);
|
||||
}
|
||||
if (m.len() as u64) < height as u64 * stride as u64 {
|
||||
return Err(PixmanError::InsufficientMemory);
|
||||
}
|
||||
let (width, height, stride) =
|
||||
match (width.try_into(), height.try_into(), stride.try_into()) {
|
||||
(Ok(w), Ok(h), Ok(s)) => (w, h, s),
|
||||
_ => return Err(PixmanError::SizeOverflow),
|
||||
};
|
||||
if m.as_ptr() as usize % 4 != 0 {
|
||||
return Err(PixmanError::UnalignedMemory);
|
||||
}
|
||||
let data = unsafe {
|
||||
pixman_image_create_bits_no_clear(
|
||||
format.raw() as _,
|
||||
width,
|
||||
height,
|
||||
m.as_ptr() as _,
|
||||
stride,
|
||||
)
|
||||
};
|
||||
if data.is_null() {
|
||||
return Err(PixmanError::Internal);
|
||||
}
|
||||
Ok(data)
|
||||
})??;
|
||||
Ok(Self {
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
memory,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn fill(&self, r: u8, g: u8, b: u8, a: u8) -> Result<(), PixmanError> {
|
||||
self.memory.access(|_| {
|
||||
let bx = Box32 {
|
||||
x1: 0,
|
||||
y1: 0,
|
||||
x2: self.width as _,
|
||||
y2: self.height as _,
|
||||
};
|
||||
let color = Color {
|
||||
red: (r as u16) << 8,
|
||||
green: (g as u16) << 8,
|
||||
blue: (b as u16) << 8,
|
||||
alpha: (a as u16) << 8,
|
||||
};
|
||||
unsafe {
|
||||
pixman_image_fill_boxes(OP_SRC.raw() as PixmanOp, self.data, &color, 1, &bx);
|
||||
}
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_image<U>(&self, over: &Image<U>, x: i32, y: i32) -> Result<(), PixmanError>
|
||||
where
|
||||
U: PixmanMemory,
|
||||
PixmanError: From<<U as PixmanMemory>::E>,
|
||||
{
|
||||
self.memory.access(|_| {
|
||||
over.memory.access(|_| unsafe {
|
||||
pixman_image_composite32(
|
||||
OP_OVER.raw(),
|
||||
over.data,
|
||||
ptr::null_mut(),
|
||||
self.data,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
over.width as _,
|
||||
over.height as _,
|
||||
);
|
||||
})
|
||||
})??;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn memory(&self) -> &T {
|
||||
&self.memory
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Image<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
pixman_image_unref(self.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue