// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. // // StratoVirt is licensed under Mulan PSL v2. // You can use this software according to the terms and conditions of the Mulan // PSL v2. // You may obtain a copy of Mulan PSL v2 at: // http://license.coscl.org.cn/MulanPSL2 // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. // See the Mulan PSL v2 for more details. use bitintr::Popcnt; use util::pixman::{ pixman_format_a, pixman_format_b, pixman_format_bpp, pixman_format_code_t, pixman_format_depth, pixman_format_g, pixman_format_r, pixman_image_get_data, pixman_image_get_format, pixman_image_get_height, pixman_image_get_stride, pixman_image_get_width, pixman_image_t, pixman_image_unref, }; #[derive(Clone, Default)] pub struct ColorInfo { /// Mask color. pub mask: u32, /// Shift to the lowest bit pub shift: u8, /// Max bits. pub max: u8, /// Color bits. pub bits: u8, } impl ColorInfo { pub fn set_color_info(&mut self, shift: u8, max: u16) { self.mask = (max as u32) << (shift as u32); self.shift = shift; self.max = if max == 0 { 0xFF } else { max as u8 }; self.bits = max.popcnt() as u8; } } #[derive(Clone, Default)] pub struct PixelFormat { /// Bits per pixel. pub pixel_bits: u8, /// Bytes per pixel. pub pixel_bytes: u8, /// Color depth. pub depth: u8, /// Red info. pub red: ColorInfo, /// Green info. pub green: ColorInfo, /// Blue info. pub blue: ColorInfo, /// Alpha channel. pub alpha_chl: ColorInfo, } impl PixelFormat { // Pixelformat_from_pixman. pub fn init_pixelformat(&mut self) { let fmt = pixman_format_code_t::PIXMAN_x8r8g8b8 as u32; self.pixel_bits = pixman_format_bpp(fmt); self.pixel_bytes = self.pixel_bits / 8; self.depth = pixman_format_depth(fmt); self.alpha_chl.bits = pixman_format_a(fmt); self.red.bits = pixman_format_r(fmt); self.green.bits = pixman_format_g(fmt); self.blue.bits = pixman_format_b(fmt); self.alpha_chl.shift = self.blue.bits + self.green.bits + self.red.bits; self.red.shift = self.blue.bits + self.green.bits; self.green.shift = self.blue.bits; self.blue.shift = 0; self.alpha_chl.max = ((1 << self.alpha_chl.bits) - 1) as u8; self.red.max = ((1 << self.red.bits) - 1) as u8; self.green.max = ((1 << self.green.bits) - 1) as u8; self.blue.max = ((1 << self.blue.bits) - 1) as u8; self.alpha_chl.mask = self.alpha_chl.max.wrapping_shl(self.alpha_chl.shift as u32) as u32; self.red.mask = self.red.max.wrapping_shl(self.red.shift as u32) as u32; self.green.mask = self.green.max.wrapping_shl(self.green.shift as u32) as u32; self.blue.mask = self.blue.max.wrapping_shl(self.blue.shift as u32) as u32; } pub fn is_default_pixel_format(&self) -> bool { // Check if type is PIXMAN_TYPE_ARGB. if self.red.shift <= self.green.shift || self.green.shift <= self.blue.shift || self.blue.shift != 0 { return false; } // Check if format is PIXMAN_x8r8g8b8. if self.pixel_bits != 32 || self.alpha_chl.bits != 0 || self.red.bits != 8 || self.green.bits != 8 || self.blue.bits != 8 { return false; } true } } pub fn get_image_width(image: *mut pixman_image_t) -> i32 { unsafe { pixman_image_get_width(image as *mut pixman_image_t) as i32 } } pub fn get_image_height(image: *mut pixman_image_t) -> i32 { unsafe { pixman_image_get_height(image as *mut pixman_image_t) as i32 } } pub fn get_image_stride(image: *mut pixman_image_t) -> i32 { unsafe { pixman_image_get_stride(image as *mut pixman_image_t) } } pub fn get_image_data(image: *mut pixman_image_t) -> *mut u32 { unsafe { pixman_image_get_data(image as *mut pixman_image_t) } } pub fn get_image_format(image: *mut pixman_image_t) -> pixman_format_code_t { unsafe { pixman_image_get_format(image as *mut pixman_image_t) } } /// Bpp: bit per pixel pub fn bytes_per_pixel() -> usize { ((pixman_format_bpp(pixman_format_code_t::PIXMAN_x8r8g8b8 as u32) + 7) / 8) as usize } /// Decrease the reference of image /// # Arguments /// /// * `image` - the pointer to image in pixman pub fn unref_pixman_image(image: *mut pixman_image_t) { if image.is_null() { return; } unsafe { pixman_image_unref(image as *mut pixman_image_t) }; }