Closed Draghtnod closed 6 years ago
Hi, can you pastebin your entire dmesg? There you should see that no panel or bridge or output in general can get registered. IMHO This should be why it can't find dri/card0.
Complete dmesg: https://pastebin.com/raw/9QRC7JTG I don't see anything unusual. It's an OrangePI Zero running current Armbian Stretch. Applying this dts https://pastebin.com/raw/yTEkUpjX had no effect. :disappointed:
It seems drm is not compiled in kernel. So try to enable it and recompile(drm-sun4i). For dts, you could use latest kernel >= 4.17, where Mali node is already present for H3.
Ok, i removed the dts overlay, upgraded to 4.17 and recompiled the driver. Still no /dev/dri/*. Modprobing sun4i-drm works silently.
CONFIG_DRM_SUN4I=y
CONFIG_DRM_SUN4I_HDMI=y
CONFIG_DRM_SUN4I_HDMI_CEC=y
CONFIG_DRM_SUN4I_BACKEND=y
CONFIG_DRM_SUN8I_DW_HDMI=y
CONFIG_DRM_SUN8I_MIXER=y
$ sudo modprobe sun4i-drm
$ sudo modprobe sun4i-frontend
$ sudo modprobe sun4i-backend
$ sudo insmod mali.ko
$ ls /dev/dri
ls: cannot access '/dev/dri': No such file or directory
I tried Mali driver version r6p2 and r8p1, no difference. Dmesg: https://pastebin.com/raw/M1HjzjQP
Modprobing should leave a trace in dmesg. Did you get dmesg before or after modprobe? If before, please pastebin dmesg after modprobe. Thanks
The dmesg was after the modprobe. No trace, except for the mali driver.
Ah, try changing loglevel=7 instead of loglevel=1 in your bootargs, this will make kernel more verbose. Then repastebin dmesg. Thanks
I am the one that has to thank you Mr. Benetti! Without you i woulnd't have a clue where to search.
Ok, loglevel=10, same procedure. Doesn't seem to produce more log entries. Still nothing from sun4i-drm and friends. https://pastebin.com/raw/2Ygh0JmD
@Draghtnod That all is really strange. You can try to compile SUN4I DRM as a module just to make sure it is loaded.By the way, "modprobe sun4i-drm" IMHO makes no sense as soon as you compile DRM into the kernel. You can setup your config as below:
CONFIG_DRM_SUN4I=m CONFIG_DRM_SUN4I_HDMI=m CONFIG_DRM_SUN4I_HDMI_CEC=y CONFIG_DRM_SUN4I_BACKEND=m CONFIG_DRM_SUN8I_DW_HDMI=m CONFIG_DRM_SUN8I_MIXER=m
After you recompile your image you can issue "lsmod" to see what is really loaded. And please pastebin your kernel config and device tree files too.
This isn't a Mali driver issue.
I finally had time to contunue pursuing this endeavour and tried to compile the Kernel with the DRM_SUN4I as Modules. Switching any of these CONFIG_DRM_SUN4I=m CONFIG_DRM_SUN4I_BACKEND=m CONFIG_DRM_SUN8I_MIXER=m to m will break the compilation process. Sometimes with error, sometimes without. Turning them to y or n will compile just fine.
While searching i noticed, that insmod mali.ko
will create /dev/mali
, but not /dev/dri/card0
. And there is a separate mali_drm
module here, which won't compile because drm_sman.h
is missing in mainline kernel. Maybe mali_drm will create the /dev/dri/card0
device? I couldn't find any documentation on this. :/
You should ask on linux-sunxi irc. You can't find /dev/dri/card0 because of wrong drm setup in your kernel. Mali should be OK at that point. On irc they can help you for drm to work. And mali_drm as I know won't show up /dev/dri/card0.
Ok thank you. Ill try to find help in IRC. Meanwhile i tried to patch mali_drm to compile with mainline. But phew.. Its not only the drm_sman, i glued that. There are lots of things restructured and renamed. That code seems to be very old.
@Draghtnod "to m will break the compilation process"
I don't believe you :-)) .. because this is just impossible. DRM can be compiled as modules, it has been proved by many people with different kernel versions. If this happens can you pastebin the compilation error ? You can also analyze my config which is 100% working. https://pastebin.com/72LttH3E
And you don't need mali_drm.
I am using the docker support of armbian build.
git checkout https://github.com/armbian/build.git
cd build
docker build -t armbian-kenel .
docker run -it armbian-kenel
I tried it about 20 times. No luck with m.
Nevertheless, I found the problem with some help of the linux-sunxi team. The problem was the missing de (display-engine) node in the device tree. Adding this will cause the sun4i-drm to start up at boot and throw an error, becuase the system is headless. Patching the kernel with this new patch from Paul today, the /dev/dri/card0 finally shows up.
Using the mali driver + sun4i-drm + wayland version of mali-blob + GBM, i should finally be able to render stuff headless. Maybe tomorrow i'll know. :)
@Draghtnod Nice to hear that you have some progress. Now I understand that you're trying to render without HDMI display connected. I have never run this scenario.
Alright i found a little time again to further pursue this adventure.
/dev/mali is present /dev/dri/card0 is present Mali Blobs user space driver, wayland version (for GBM support) r6p2 is installed A little Rust program to utilize GBM for a virtual display and EGL is written.
These lines
let apis = egl::query_string( egl::EGL_NO_DISPLAY, egl::EGL_EXTENSIONS );
if apis.is_some() {
println!( "Display Extensions: {}", apis.unwrap().to_str().unwrap_or( "unwrap error" ) );
}
let dri = OpenOptions::new().read( true ).write( true ).open( "/dev/dri/card0" ).unwrap();
let gbm = unsafe { gbm_sys::gbm_create_device( dri.as_raw_fd() ) };
output this:
Display Extensions: EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_platform_gbm EGL_KHR_platform_wayland
MESA-LOADER: failed to retrieve device information
gbm: failed to open any driver (search paths /usr/lib/arm-linux-gnueabihf/dri:${ORIGIN}/dri:/usr/lib/dri)
gbm: Last dlopen error: /usr/lib/dri/sun4i-drm_dri.so: cannot open shared object file: No such file or directory
failed to load driver: sun4i-drm
No Display: 0x3000
Process exited with code 0.
dmesg:
[ 119.472305] mali: loading out-of-tree module taints kernel.
[ 119.480885] Allwinner sunXi mali glue initialized
[ 119.483224] Mali:
[ 119.483234] Found Mali GPU Mali-400 MP r1p1
[ 119.483679] Mali:
[ 119.483685] 2+0 PP cores initialized
[ 119.484711] Mali:
[ 119.484719] Mali device driver loaded
[ 193.857641] [drm:drm_stub_open]
[ 193.857702] [drm:drm_open] pid = 1201, minor = 0
[ 193.857901] [drm:drm_open]
[ 194.940518] [drm:drm_ioctl] pid=1201, dev=0xe200, auth=1, DRM_IOCTL_VERSION
[ 194.940541] [drm:drm_ioctl] pid=1201, dev=0xe200, auth=1, DRM_IOCTL_VERSION
[ 197.611710] [drm:drm_ioctl] pid=1201, dev=0xe200, auth=1, DRM_IOCTL_GET_CAP
[ 197.772350] [drm:drm_release] open_count = 1
[ 197.772366] [drm:drm_release] pid = 1204, device = 0xe200, open_count = 1
[ 197.772389] [drm:drm_lastclose]
[ 197.772395] [drm:drm_lastclose] driver lastclose completed
Appearantly there is a sun4i-drm_dri.so
missing. I found some more error messages around the web with that problem as well, but no info on how to find or compile this file or where it comes from. The name suggests it belongs to the sunxi DRM drivers, but i didn't find anything there. Maybe someone of you has seen this before?
If i linkt the missing /usr/lib/dri/sun4i-drm_dri.so
to the mali blobs libMali.so
, it complains about missing functions:
Display Extensions: EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_platform_gbm EGL_KHR_platform_wayland
MESA-LOADER: failed to retrieve device information
gbm: driver exports no extensions (/usr/lib/libEGL.so.1: undefined symbol: __driDriverExtensions)failed to load driver: sun4i-drm
No Display: 0x3000
Process exited with code 0.
This issue came up here as well. No solution tho.. It seems to be the DRM interface of the device driver. So sunxi-mali should be the right spot. Correct?
MESA-LOADER
lol u did mesa again mesa libs must not be included in library path. Also make link "libwayland-egl.so.1" > "libwayland-egl.so" where your mali libs located
Duh.. Thank you.. I totally forgot to copy the mali-blobs to the compiling system.
gbm_create_device() works now, egl_get_display() too! New Error now at egl_initialize (yay!):
Display Extensions: EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_platform_gbm EGL_KHR_platform_wayland
Initialize failed: 0x3003
Process exited with code 0.
0x3003
is EGL_BAD_ALLOC
. Looks like the driver is not happy with the drm memory allocations. :/ This thing really doesn't like to render stuff.
@Draghtnod It seems to me that we already had this problem before. Try searching in closed issues , there should be a big discussion about it.
@Draghtnod this can be:
ldd your_app
drm_kms_helper.drm_fbdev_overalloc=300
Holy Moly it WORKS!!
Display Extensions: EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_platform_gbm EGL_KHR_platform_wayland
GBM: 0xb6821030
Display: 0x1
EGL initialized with v1.4
apis: OpenGL_ES
vendor: ARM
version: 1.4 Linux-r6p2-01rel0
extensions: EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_EXT_image_dma_buf_import EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_gl_renderbuffer_image EGL_KHR_reusable_sync EGL_KHR_fence_sync EGL_KHR_swap_buffers_with_damage EGL_EXT_swap_buffers_with_damage EGL_KHR_lock_surface EGL_KHR_lock_surface2 EGL_EXT_create_context_robustness EGL_ANDROID_blob_cache EGL_KHR_create_context EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_create_context_no_error
EGL_RENDERABLE_TYPE: 5
That was NOT obvious at all. This driver and the mali blobs feel like a big horrible hack. Here is how it works:
Basically every function you call and resource you use is contained within the sunxi-mali and mali-blobs ecosystem. No external library or resource is touched at all, even if all the functions, libraries are called this way and all the docs you find tell a different story. Not intuitive at all.
Thank you again everyone for all the help! I'll write a little HOTWO in the armbian forums. Maybe someone with a H2+/H3 is crazy enough to try to do the same.
@Draghtnod Can you post your complete rust test program and requirements to build it? I'm trying to get the Mali driver and r6p2 wayland blobs working on an A64 and your rust program can help me see if I have it working.
@Draghtnod Here's what I have to try to run your sample rust code:
src/main.rs:
extern crate egl;
extern crate gbm_sys;
use std::fs::OpenOptions;
use std::os::unix::io::AsRawFd;
// This is the main function
fn main() {
// Print text to the console
println!("GBM Test");
let apis = egl::query_string( egl::EGL_NO_DISPLAY, egl::EGL_EXTENSIONS );
if apis.is_some() {
println!( "Display Extensions: {}", apis.unwrap().to_str().unwrap_or( "unwrap error" ) );
}
let dri = OpenOptions::new().read( true ).write( true ).open( "/dev/mali" ).unwrap();
let gbm = unsafe { gbm_sys::gbm_create_device( dri.as_raw_fd() ) };
}
Cargo.toml:
[package]
name = "gbm-test"
version = "0.1.0"
authors = ["John P. Masseria <jpmasseria@gmail.com>"]
[dependencies]
egl = "0.2.7"
gbm-sys = "0.1.0"
But cargo build
yields error[E0425]: cannot find function
gbm_create_devicein module
gbm_sys`
error[E0425]: cannot find function `gbm_create_device` in module `gbm_sys`
--> src/main.rs:20:33
|
20 | let gbm = unsafe { gbm_sys::gbm_create_device( dri.as_raw_fd() ) };
| ^^^^^^^^^^^^^^^^^ not found in `gbm_sys`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0425`.
error: Could not compile `gbm-test`.
@HeatfanJohn Sorry I'm a bit late. You have to use the "gen" feature of gbm_sys, so the gmb_create_device function gets wired to the mali blobs, to which libgbm should symlink to. Make sure you have uninstalled the genuine libgbm. I had problems with gbm_sys and the gen feature, so i forked it and made some bugfixes. Works fine for me now. :) Good Luck!
extern crate log;
extern crate gbm;
extern crate egl;
use std::fs::{ OpenOptions, File };
use self::gbm::AsRaw;
/// A virtual EGL Display based on a GBM buffer.
#[allow(dead_code)]
pub struct GBMEGLDisplay {
gbm_device: gbm::Device< File >,
egl_display: egl::EGLDisplay,
}
impl GBMEGLDisplay {
/// Creates a virtual EGL Display based on a GBM buffer and makes it current.
/// # Arguments
/// `size` - Width and height of the display buffer in pixels.
pub fn create( size : ( u32, u32 ) ) -> Result< GBMEGLDisplay, () > {
// Print available EGL Display Extensions
debug!( "EGL Display Extensions: {}", egl::query_string( egl::EGL_NO_DISPLAY, egl::EGL_EXTENSIONS ).unwrap_or_default().to_str().unwrap_or( "unwrap error" ) );
// Open the mali device
let mali_device = try!( OpenOptions::new().read( true ).write( true ).open( "/dev/mali" ).or_else( |error| {
error!( "Could not access /dev/mali device: {:?}", error );
Err(())
} ) );
// Create a GBM device from the mali device
let gbm_device = try!( gbm::Device::new( mali_device ).or_else( |error| {
error!( "Could not create GBM device: {:?}", error );
Err(())
} ) );
// Get an EGL Display from the GBM device
let egl_display = try!( egl::get_display( gbm_device.as_raw_mut() as egl::EGLDisplay ).ok_or_else( || {
error!( "Could not aquire an EGL display: Error {:#X?}", egl::get_error() );
()
} ) );
// Initialize EGL
let mut maj = 0;
let mut min = 0;
if !egl::initialize( egl_display, &mut maj, &mut min ) {
error!( "Initialize failed: Error {:#X?}", egl::get_error() );
return Err(());
}
info!( "EGL initialized with v{}.{}", maj, min );
// Print Various infos
debug!( "EGL Version: {}", egl::query_string( egl_display, egl::EGL_VERSION ).unwrap_or_default().to_str().unwrap_or( "unwrap error" ) );
debug!( "EGL Vendor: {}", egl::query_string( egl_display, egl::EGL_VENDOR ).unwrap_or_default().to_str().unwrap_or( "unwrap error" ) );
debug!( "EGL Apis: {}", egl::query_string( egl_display, egl::EGL_CLIENT_APIS ).unwrap_or_default().to_str().unwrap_or( "unwrap error" ) );
debug!( "EGL Extensions: {}", egl::query_string( egl_display, egl::EGL_EXTENSIONS ).unwrap_or_default().to_str().unwrap_or( "unwrap error" ) );
// Choose a suitable config
let attrib_list = [
egl::EGL_RENDERABLE_TYPE, egl::EGL_OPENGL_ES2_BIT,
egl::EGL_CONFORMANT, egl::EGL_OPENGL_ES2_BIT,
egl::EGL_SURFACE_TYPE, egl::EGL_PBUFFER_BIT,
egl::EGL_BIND_TO_TEXTURE_RGB, egl::EGL_TRUE as egl::EGLint,
egl::EGL_BIND_TO_TEXTURE_RGBA, egl::EGL_TRUE as egl::EGLint,
egl::EGL_RED_SIZE, 8,
egl::EGL_GREEN_SIZE, 8,
egl::EGL_BLUE_SIZE, 8,
egl::EGL_ALPHA_SIZE, 0,
egl::EGL_DEPTH_SIZE, 0,
egl::EGL_STENCIL_SIZE, 0,
egl::EGL_NONE
];
let config = try!( egl::choose_config( egl_display, &attrib_list, 1 ).ok_or_else( || {
error!( "Config not available: {:#X?}", egl::get_error() );
egl::terminate( egl_display );
()
} ) );
// Print some debug info
let mut value = 0;
if egl::get_config_attrib( egl_display, config, egl::EGL_RED_SIZE, &mut value ) { debug!( "EGL_RED_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_GREEN_SIZE, &mut value ) { debug!( "EGL_GREEN_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_BLUE_SIZE, &mut value ) { debug!( "EGL_BLUE_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_ALPHA_SIZE, &mut value ) { debug!( "EGL_ALPHA_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_BUFFER_SIZE, &mut value ) { debug!( "EGL_BUFFER_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_DEPTH_SIZE, &mut value ) { debug!( "EGL_DEPTH_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_STENCIL_SIZE, &mut value ) { debug!( "EGL_STENCIL_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_LUMINANCE_SIZE, &mut value ) { debug!( "EGL_LUMINANCE_SIZE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_COLOR_BUFFER_TYPE, &mut value ) { debug!( "EGL_COLOR_BUFFER_TYPE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_MAX_PBUFFER_WIDTH, &mut value ) { debug!( "EGL_MAX_PBUFFER_WIDTH: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_MAX_PBUFFER_HEIGHT, &mut value ) { debug!( "EGL_MAX_PBUFFER_HEIGHT: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_MAX_PBUFFER_PIXELS, &mut value ) { debug!( "EGL_MAX_PBUFFER_PIXELS: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_NATIVE_RENDERABLE, &mut value ) { debug!( "EGL_NATIVE_RENDERABLE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_RENDERABLE_TYPE, &mut value ) { debug!( "EGL_RENDERABLE_TYPE: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_CONFORMANT, &mut value ) { debug!( "EGL_CONFORMANT: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_BIND_TO_TEXTURE_RGB, &mut value ) { debug!( "EGL_BIND_TO_TEXTURE_RGB: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_BIND_TO_TEXTURE_RGBA, &mut value ) { debug!( "EGL_BIND_TO_TEXTURE_RGBA: {}", value ); }
if egl::get_config_attrib( egl_display, config, egl::EGL_MATCH_NATIVE_PIXMAP, &mut value ) { debug!( "EGL_MATCH_NATIVE_PIXMAP: {}", value ); }
// Create a context
let attrib_list = [
egl::EGL_CONTEXT_CLIENT_VERSION, 2,
egl::EGL_NONE
];
let context = try!( egl::create_context( egl_display, config, egl::EGL_NO_CONTEXT, &attrib_list ).ok_or_else( || {
error!( "Could not create context: {:#X?}", egl::get_error() );
egl::terminate( egl_display );
()
} ) );
// Create a render buffer
let attrib_list = [
egl::EGL_WIDTH, size.0 as egl::EGLint,
egl::EGL_HEIGHT, size.1 as egl::EGLint,
egl::EGL_NONE
];
let pbuffer = try!( egl::create_pbuffer_surface( egl_display, config, &attrib_list ).ok_or_else( || {
error!( "Could not create pbuffer surface: {:#X?}", egl::get_error() );
egl::terminate( egl_display );
()
} ) );
// Select the render buffer
if !egl::make_current( egl_display, pbuffer, pbuffer, context ) {
error!( "Make current failed: {:#X?}", egl::get_error() );
egl::terminate( egl_display );
return Err(());
}
Ok( GBMEGLDisplay {
gbm_device,
egl_display,
} )
}
}
impl Drop for GBMEGLDisplay {
/// Releases internal resources.
fn drop( &mut self ) {
if !egl::terminate( self.egl_display ) {
error!( "Could not terminate EGL display: {:#X?}", egl::get_error() );
} else {
debug!( "EGL display terminated.")
}
}
}
Cargo.toml
[dependencies.gbm]
git = "https://github.com/Draghtnod/gbm.rs.git"
default-features = false
features = [ "gen" ]
[dependencies.opengles]
git = "https://github.com/Draghtnod/rust-opengles.git"
[dependencies]
log = "*"
egl = "*"
...
Greetings!
Am i missing something?