strat9_kernel/framebuffer/x86/mod.rs
1//! SIMD pixel operations for x86_64.
2//!
3//! Currently exposes the SSE2 (+SSSE3 convert) implementations only.
4//!
5//! AVX2/AVX512 variants are TEMPORARILY removed: nightly
6//! `1.100.0-nightly (c656540d, LLVM 23.1-rust)` mis-compiles the custom
7//! `x86_64-unknown-none` target by emitting `+soft-float` into every
8//! function's target-features, which makes X86 instruction selection abort
9//! on 256-bit intrinsics (`llvm.x86.avx2.pshuf.b`) with:
10//! "Do not know how to split the result of this operator!"
11//! Restore `avx2`/`avx512` once the toolchain issue is resolved. The
12//! streaming-store paths are disabled too; cached SSE2 remains available.
13
14use crate::framebuffer::{generic, FramebufferOps};
15pub mod sse2;
16
17pub fn detect_and_init_ops() -> FramebufferOps {
18 let cpuid = raw_cpuid::CpuId::new();
19
20 let has_sse41 = cpuid
21 .get_feature_info()
22 .map_or(false, |info| info.has_sse41());
23
24 let has_ssse3 = cpuid
25 .get_feature_info()
26 .map_or(false, |info| info.has_ssse3());
27
28 let has_sse2 = cpuid
29 .get_feature_info()
30 .map_or(false, |info| info.has_sse2());
31
32 if has_sse41 || has_sse2 {
33 // convert_bgr_to_argb requires SSSE3 (pshufb). Without it, use the scalar path.
34 let convert: crate::framebuffer::FnConvert = if has_ssse3 {
35 sse2::convert_bgr_to_argb_sse2
36 } else {
37 generic::convert_bgr_to_argb_generic
38 };
39 FramebufferOps {
40 fill: sse2::fill_sse2,
41 blit: sse2::blit_sse2,
42 blend: sse2::blend_sse2,
43 convert,
44 }
45 } else {
46 FramebufferOps {
47 fill: generic::fill_generic,
48 blit: generic::blit_generic,
49 blend: generic::blend_generic,
50 convert: generic::convert_bgr_to_argb_generic,
51 }
52 }
53}