Added logging to egl&winit + small bugfixes
- Added logging to winit & egl - Fixed winit pointer scroll event only yielding horizontal events - Fixed unsupported double_buffering for egl
This commit is contained in:
parent
4053d2bc30
commit
2453545329
|
@ -126,8 +126,14 @@ impl EGLContext {
|
||||||
///
|
///
|
||||||
/// This method is marked unsafe, because the contents of `Native` cannot be verified and msy
|
/// This method is marked unsafe, because the contents of `Native` cannot be verified and msy
|
||||||
/// contain dangeling pointers are similar unsafe content
|
/// contain dangeling pointers are similar unsafe content
|
||||||
pub unsafe fn new(native: Native, mut attributes: GlAttributes, reqs: PixelFormatRequirements)
|
pub unsafe fn new<L>(native: Native, mut attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L)
|
||||||
-> Result<EGLContext, CreationError> {
|
-> Result<EGLContext, CreationError>
|
||||||
|
where L: Into<Option<::slog::Logger>>
|
||||||
|
{
|
||||||
|
let logger = logger.into();
|
||||||
|
let log = ::slog_or_stdlog(logger.clone()).new(o!("smithay_module" => "renderer_egl"));
|
||||||
|
trace!(log, "Loading libEGL");
|
||||||
|
|
||||||
let lib = Library::new("libEGL.so.1")?;
|
let lib = Library::new("libEGL.so.1")?;
|
||||||
let egl = ffi::egl::Egl::load_with(|sym| {
|
let egl = ffi::egl::Egl::load_with(|sym| {
|
||||||
let name = CString::new(sym).unwrap();
|
let name = CString::new(sym).unwrap();
|
||||||
|
@ -138,29 +144,32 @@ impl EGLContext {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// If no version is given, try OpenGLES 3.0, if available,
|
// If no version is given, try OpenGLES 3.0, if available,
|
||||||
// fallback to 2.0 otherwise
|
// fallback to 2.0 otherwise
|
||||||
let version = match attributes.version {
|
let version = match attributes.version {
|
||||||
Some((3, x)) => (3, x),
|
Some((3, x)) => (3, x),
|
||||||
Some((2, x)) => (2, x),
|
Some((2, x)) => (2, x),
|
||||||
None => {
|
None => {
|
||||||
|
debug!(log, "Trying to initialize EGL with OpenGLES 3.0");
|
||||||
attributes.version = Some((3, 0));
|
attributes.version = Some((3, 0));
|
||||||
match EGLContext::new(native, attributes, reqs) {
|
match EGLContext::new(native, attributes, reqs, logger.clone()) {
|
||||||
Ok(x) => return Ok(x),
|
Ok(x) => return Ok(x),
|
||||||
Err(_) => {
|
Err(err) => {
|
||||||
// TODO log
|
warn!(log, "EGL OpenGLES 3.0 Initialization failed with {}", err);
|
||||||
|
debug!(log, "Trying to initialize EGL with OpenGLES 2.0");
|
||||||
attributes.version = Some((2, 0));
|
attributes.version = Some((2, 0));
|
||||||
return EGLContext::new(native, attributes, reqs);
|
return EGLContext::new(native, attributes, reqs, logger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some((1, _)) => {
|
Some((1, _)) => {
|
||||||
// TODO logging + error, 1.0 not supported
|
error!(log, "OpenGLES 1.* is not supported by the EGL renderer backend");
|
||||||
unimplemented!()
|
return Err(CreationError::OpenGlVersionNotSupported)
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(version) => {
|
||||||
// TODO logging + error, version not supported
|
error!(log, "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", version);
|
||||||
unimplemented!()
|
return Err(CreationError::OpenGlVersionNotSupported)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,31 +188,38 @@ impl EGLContext {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
debug!(log, "EGL No-Display Extensions: {:?}", dp_extensions);
|
||||||
|
|
||||||
let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e);
|
let has_dp_extension = |e: &str| dp_extensions.iter().any(|s| s == e);
|
||||||
|
|
||||||
let display = match native {
|
let display = match native {
|
||||||
Native::X11(display, _) if has_dp_extension("EGL_KHR_platform_x11") &&
|
Native::X11(display, _) if has_dp_extension("EGL_KHR_platform_x11") &&
|
||||||
egl.GetPlatformDisplay.is_loaded() => {
|
egl.GetPlatformDisplay.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11");
|
||||||
egl.GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
|
egl.GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
Native::X11(display, _) if has_dp_extension("EGL_EXT_platform_x11") &&
|
Native::X11(display, _) if has_dp_extension("EGL_EXT_platform_x11") &&
|
||||||
egl.GetPlatformDisplayEXT.is_loaded() => {
|
egl.GetPlatformDisplayEXT.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11");
|
||||||
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
|
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
Native::Gbm(display, _) if has_dp_extension("EGL_KHR_platform_gbm") &&
|
Native::Gbm(display, _) if has_dp_extension("EGL_KHR_platform_gbm") &&
|
||||||
egl.GetPlatformDisplay.is_loaded() => {
|
egl.GetPlatformDisplay.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm");
|
||||||
egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
Native::Gbm(display, _) if has_dp_extension("EGL_MESA_platform_gbm") &&
|
Native::Gbm(display, _) if has_dp_extension("EGL_MESA_platform_gbm") &&
|
||||||
egl.GetPlatformDisplayEXT.is_loaded() => {
|
egl.GetPlatformDisplayEXT.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm");
|
||||||
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null())
|
||||||
}
|
}
|
||||||
|
|
||||||
Native::Wayland(display, _) if has_dp_extension("EGL_KHR_platform_wayland") &&
|
Native::Wayland(display, _) if has_dp_extension("EGL_KHR_platform_wayland") &&
|
||||||
egl.GetPlatformDisplay.is_loaded() => {
|
egl.GetPlatformDisplay.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_KHR_platform_wayland");
|
||||||
egl.GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR,
|
egl.GetPlatformDisplay(ffi::egl::PLATFORM_WAYLAND_KHR,
|
||||||
display as *mut _,
|
display as *mut _,
|
||||||
ptr::null())
|
ptr::null())
|
||||||
|
@ -211,6 +227,7 @@ impl EGLContext {
|
||||||
|
|
||||||
Native::Wayland(display, _) if has_dp_extension("EGL_EXT_platform_wayland") &&
|
Native::Wayland(display, _) if has_dp_extension("EGL_EXT_platform_wayland") &&
|
||||||
egl.GetPlatformDisplayEXT.is_loaded() => {
|
egl.GetPlatformDisplayEXT.is_loaded() => {
|
||||||
|
trace!(log, "EGL Display Initialization via EGL_EXT_platform_wayland");
|
||||||
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT,
|
egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_WAYLAND_EXT,
|
||||||
display as *mut _,
|
display as *mut _,
|
||||||
ptr::null())
|
ptr::null())
|
||||||
|
@ -218,7 +235,10 @@ impl EGLContext {
|
||||||
|
|
||||||
Native::X11(display, _) |
|
Native::X11(display, _) |
|
||||||
Native::Gbm(display, _) |
|
Native::Gbm(display, _) |
|
||||||
Native::Wayland(display, _) => egl.GetDisplay(display as *mut _),
|
Native::Wayland(display, _) => {
|
||||||
|
trace!(log, "Default EGL Display Initialization via GetDisplay");
|
||||||
|
egl.GetDisplay(display as *mut _)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let egl_version = {
|
let egl_version = {
|
||||||
|
@ -229,6 +249,9 @@ impl EGLContext {
|
||||||
return Err(CreationError::OsError(String::from("eglInitialize failed")));
|
return Err(CreationError::OsError(String::from("eglInitialize failed")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!(log, "EGL Initialized");
|
||||||
|
info!(log, "EGL Version: {:?}", (major, minor));
|
||||||
|
|
||||||
(major, minor)
|
(major, minor)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -243,7 +266,10 @@ impl EGLContext {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info!(log, "EGL Extensions: {:?}", extensions);
|
||||||
|
|
||||||
if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 {
|
if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 {
|
||||||
|
error!(log, "OpenGLES not supported by the underlying EGL implementation");
|
||||||
return Err(CreationError::OpenGlVersionNotSupported);
|
return Err(CreationError::OpenGlVersionNotSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,10 +277,13 @@ impl EGLContext {
|
||||||
let mut out: Vec<c_int> = Vec::with_capacity(37);
|
let mut out: Vec<c_int> = Vec::with_capacity(37);
|
||||||
|
|
||||||
if egl_version >= (1, 2) {
|
if egl_version >= (1, 2) {
|
||||||
|
trace!(log, "Setting COLOR_BUFFER_TYPE to RGB_BUFFER");
|
||||||
out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int);
|
out.push(ffi::egl::COLOR_BUFFER_TYPE as c_int);
|
||||||
out.push(ffi::egl::RGB_BUFFER as c_int);
|
out.push(ffi::egl::RGB_BUFFER as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!(log, "Setting SURFACE_TYPE to WINDOW");
|
||||||
|
|
||||||
out.push(ffi::egl::SURFACE_TYPE as c_int);
|
out.push(ffi::egl::SURFACE_TYPE as c_int);
|
||||||
// TODO: Some versions of Mesa report a BAD_ATTRIBUTE error
|
// TODO: Some versions of Mesa report a BAD_ATTRIBUTE error
|
||||||
// if we ask for PBUFFER_BIT as well as WINDOW_BIT
|
// if we ask for PBUFFER_BIT as well as WINDOW_BIT
|
||||||
|
@ -263,19 +292,25 @@ impl EGLContext {
|
||||||
match version {
|
match version {
|
||||||
(3, _) => {
|
(3, _) => {
|
||||||
if egl_version < (1, 3) {
|
if egl_version < (1, 3) {
|
||||||
|
error!(log, "OpenglES 3.* is not supported on EGL Versions lower then 1.3");
|
||||||
return Err(CreationError::NoAvailablePixelFormat);
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
}
|
}
|
||||||
|
trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES3");
|
||||||
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
||||||
|
trace!(log, "Setting CONFORMANT to OPENGL_ES3");
|
||||||
out.push(ffi::egl::CONFORMANT as c_int);
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
out.push(ffi::egl::OPENGL_ES3_BIT as c_int);
|
||||||
}
|
}
|
||||||
(2, _) => {
|
(2, _) => {
|
||||||
if egl_version < (1, 3) {
|
if egl_version < (1, 3) {
|
||||||
|
error!(log, "OpenglES 2.* is not supported on EGL Versions lower then 1.3");
|
||||||
return Err(CreationError::NoAvailablePixelFormat);
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
}
|
}
|
||||||
|
trace!(log, "Setting RENDERABLE_TYPE to OPENGL_ES2");
|
||||||
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
out.push(ffi::egl::RENDERABLE_TYPE as c_int);
|
||||||
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
||||||
|
trace!(log, "Setting CONFORMANT to OPENGL_ES2");
|
||||||
out.push(ffi::egl::CONFORMANT as c_int);
|
out.push(ffi::egl::CONFORMANT as c_int);
|
||||||
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
out.push(ffi::egl::OPENGL_ES2_BIT as c_int);
|
||||||
}
|
}
|
||||||
|
@ -285,46 +320,52 @@ impl EGLContext {
|
||||||
if let Some(hardware_accelerated) = reqs.hardware_accelerated {
|
if let Some(hardware_accelerated) = reqs.hardware_accelerated {
|
||||||
out.push(ffi::egl::CONFIG_CAVEAT as c_int);
|
out.push(ffi::egl::CONFIG_CAVEAT as c_int);
|
||||||
out.push(if hardware_accelerated {
|
out.push(if hardware_accelerated {
|
||||||
|
trace!(log, "Setting CONFIG_CAVEAT to NONE");
|
||||||
ffi::egl::NONE as c_int
|
ffi::egl::NONE as c_int
|
||||||
} else {
|
} else {
|
||||||
|
trace!(log, "Setting CONFIG_CAVEAT to SLOW_CONFIG");
|
||||||
ffi::egl::SLOW_CONFIG as c_int
|
ffi::egl::SLOW_CONFIG as c_int
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(color) = reqs.color_bits {
|
if let Some(color) = reqs.color_bits {
|
||||||
|
trace!(log, "Setting RED_SIZE to {}", color / 3);
|
||||||
out.push(ffi::egl::RED_SIZE as c_int);
|
out.push(ffi::egl::RED_SIZE as c_int);
|
||||||
out.push((color / 3) as c_int);
|
out.push((color / 3) as c_int);
|
||||||
|
trace!(log, "Setting GREEN_SIZE to {}", color / 3 + if color % 3 != 0 { 1 } else { 0 });
|
||||||
out.push(ffi::egl::GREEN_SIZE as c_int);
|
out.push(ffi::egl::GREEN_SIZE as c_int);
|
||||||
out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
|
out.push((color / 3 + if color % 3 != 0 { 1 } else { 0 }) as c_int);
|
||||||
|
trace!(log, "Setting BLUE_SIZE to {}", color / 3 + if color % 3 == 2 { 1 } else { 0 });
|
||||||
out.push(ffi::egl::BLUE_SIZE as c_int);
|
out.push(ffi::egl::BLUE_SIZE as c_int);
|
||||||
out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
|
out.push((color / 3 + if color % 3 == 2 { 1 } else { 0 }) as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(alpha) = reqs.alpha_bits {
|
if let Some(alpha) = reqs.alpha_bits {
|
||||||
|
trace!(log, "Setting ALPHA_SIZE to {}", alpha);
|
||||||
out.push(ffi::egl::ALPHA_SIZE as c_int);
|
out.push(ffi::egl::ALPHA_SIZE as c_int);
|
||||||
out.push(alpha as c_int);
|
out.push(alpha as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(depth) = reqs.depth_bits {
|
if let Some(depth) = reqs.depth_bits {
|
||||||
|
trace!(log, "Setting DEPTH_SIZE to {}", depth);
|
||||||
out.push(ffi::egl::DEPTH_SIZE as c_int);
|
out.push(ffi::egl::DEPTH_SIZE as c_int);
|
||||||
out.push(depth as c_int);
|
out.push(depth as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(stencil) = reqs.stencil_bits {
|
if let Some(stencil) = reqs.stencil_bits {
|
||||||
|
trace!(log, "Setting STENCIL_SIZE to {}", stencil);
|
||||||
out.push(ffi::egl::STENCIL_SIZE as c_int);
|
out.push(ffi::egl::STENCIL_SIZE as c_int);
|
||||||
out.push(stencil as c_int);
|
out.push(stencil as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(true) = reqs.double_buffer {
|
|
||||||
return Err(CreationError::NoAvailablePixelFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(multisampling) = reqs.multisampling {
|
if let Some(multisampling) = reqs.multisampling {
|
||||||
|
trace!(log, "Setting SAMPLES to {}", multisampling);
|
||||||
out.push(ffi::egl::SAMPLES as c_int);
|
out.push(ffi::egl::SAMPLES as c_int);
|
||||||
out.push(multisampling as c_int);
|
out.push(multisampling as c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if reqs.stereoscopy {
|
if reqs.stereoscopy {
|
||||||
|
error!(log, "Stereoscopy is currently unsupported (sorry!)");
|
||||||
return Err(CreationError::NoAvailablePixelFormat);
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,6 +384,7 @@ impl EGLContext {
|
||||||
return Err(CreationError::OsError(String::from("eglChooseConfig failed")));
|
return Err(CreationError::OsError(String::from("eglChooseConfig failed")));
|
||||||
}
|
}
|
||||||
if num_configs == 0 {
|
if num_configs == 0 {
|
||||||
|
error!(log, "No matching color format found");
|
||||||
return Err(CreationError::NoAvailablePixelFormat);
|
return Err(CreationError::NoAvailablePixelFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,15 +421,20 @@ impl EGLContext {
|
||||||
srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that
|
srgb: false, // TODO: use EGL_KHR_gl_colorspace to know that
|
||||||
};
|
};
|
||||||
|
|
||||||
|
info!(log, "Selected color format: {:?}", desc);
|
||||||
|
|
||||||
let mut context_attributes = Vec::with_capacity(10);
|
let mut context_attributes = Vec::with_capacity(10);
|
||||||
|
|
||||||
if egl_version >= (1, 5) || extensions.iter().any(|s| s == &"EGL_KHR_create_context") {
|
if egl_version >= (1, 5) || extensions.iter().any(|s| s == &"EGL_KHR_create_context") {
|
||||||
|
trace!(log, "Setting CONTEXT_MAJOR_VERSION to {}", version.0);
|
||||||
context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
|
context_attributes.push(ffi::egl::CONTEXT_MAJOR_VERSION as i32);
|
||||||
context_attributes.push(version.0 as i32);
|
context_attributes.push(version.0 as i32);
|
||||||
|
trace!(log, "Setting CONTEXT_MINOR_VERSION to {}", version.1);
|
||||||
context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
|
context_attributes.push(ffi::egl::CONTEXT_MINOR_VERSION as i32);
|
||||||
context_attributes.push(version.1 as i32);
|
context_attributes.push(version.1 as i32);
|
||||||
|
|
||||||
if attributes.debug && egl_version >= (1, 5) {
|
if attributes.debug && egl_version >= (1, 5) {
|
||||||
|
trace!(log, "Setting CONTEXT_OPENGL_DEBUG to TRUE");
|
||||||
context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
|
context_attributes.push(ffi::egl::CONTEXT_OPENGL_DEBUG as i32);
|
||||||
context_attributes.push(ffi::egl::TRUE as i32);
|
context_attributes.push(ffi::egl::TRUE as i32);
|
||||||
}
|
}
|
||||||
|
@ -396,26 +443,53 @@ impl EGLContext {
|
||||||
context_attributes.push(0);
|
context_attributes.push(0);
|
||||||
|
|
||||||
} else if egl_version >= (1, 3) {
|
} else if egl_version >= (1, 3) {
|
||||||
|
trace!(log, "Setting CONTEXT_CLIENT_VERSION to {}", version.0);
|
||||||
context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
|
context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
|
||||||
context_attributes.push(version.0 as i32);
|
context_attributes.push(version.0 as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
context_attributes.push(ffi::egl::NONE as i32);
|
context_attributes.push(ffi::egl::NONE as i32);
|
||||||
|
|
||||||
|
trace!(log, "Creating EGL context...");
|
||||||
let context = egl.CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr());
|
let context = egl.CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr());
|
||||||
|
|
||||||
if context.is_null() {
|
if context.is_null() {
|
||||||
match egl.GetError() as u32 {
|
match egl.GetError() as u32 {
|
||||||
ffi::egl::BAD_ATTRIBUTE => return Err(CreationError::OpenGlVersionNotSupported),
|
ffi::egl::BAD_ATTRIBUTE => {
|
||||||
|
error!(log, "Context creation failed as one or more requirements could not be met. Try removing some gl attributes or pixel format requirements");
|
||||||
|
return Err(CreationError::OpenGlVersionNotSupported);
|
||||||
|
},
|
||||||
e => panic!("eglCreateContext failed: 0x{:x}", e),
|
e => panic!("eglCreateContext failed: 0x{:x}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debug!(log, "EGL context successfully created");
|
||||||
|
|
||||||
|
let surface_attributes = {
|
||||||
|
let mut out: Vec<c_int> = Vec::with_capacity(2);
|
||||||
|
|
||||||
|
match reqs.double_buffer {
|
||||||
|
Some(true) => {
|
||||||
|
trace!(log, "Setting RENDER_BUFFER to BACK_BUFFER");
|
||||||
|
out.push(ffi::egl::RENDER_BUFFER as c_int);
|
||||||
|
out.push(ffi::egl::BACK_BUFFER as c_int);
|
||||||
|
},
|
||||||
|
Some(false) => {
|
||||||
|
trace!(log, "Setting RENDER_BUFFER to SINGLE_BUFFER");
|
||||||
|
out.push(ffi::egl::RENDER_BUFFER as c_int);
|
||||||
|
out.push(ffi::egl::SINGLE_BUFFER as c_int);
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
};
|
||||||
|
|
||||||
|
trace!(log, "Creating EGL window surface...");
|
||||||
let surface = {
|
let surface = {
|
||||||
let surface = match native {
|
let surface = match native {
|
||||||
Native::X11(_, window) |
|
Native::X11(_, window) |
|
||||||
Native::Wayland(_, window) |
|
Native::Wayland(_, window) |
|
||||||
Native::Gbm(_, window) => egl.CreateWindowSurface(display, config_id, window, ptr::null()),
|
Native::Gbm(_, window) => egl.CreateWindowSurface(display, config_id, window, surface_attributes.as_ptr()),
|
||||||
};
|
};
|
||||||
|
|
||||||
if surface.is_null() {
|
if surface.is_null() {
|
||||||
|
@ -423,7 +497,9 @@ impl EGLContext {
|
||||||
}
|
}
|
||||||
surface
|
surface
|
||||||
};
|
};
|
||||||
|
debug!(log, "EGL window surface successfully created");
|
||||||
|
|
||||||
|
info!(log, "EGL context created");
|
||||||
Ok(EGLContext {
|
Ok(EGLContext {
|
||||||
_lib: lib,
|
_lib: lib,
|
||||||
context: context as *const _,
|
context: context as *const _,
|
||||||
|
|
|
@ -25,6 +25,7 @@ use winit::os::unix::{WindowExt, get_x11_xconnection};
|
||||||
pub struct WinitGraphicsBackend {
|
pub struct WinitGraphicsBackend {
|
||||||
window: Rc<Window>,
|
window: Rc<Window>,
|
||||||
context: EGLContext,
|
context: EGLContext,
|
||||||
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abstracted event loop of a `winit` `Window` implementing the `InputBackend` trait
|
/// Abstracted event loop of a `winit` `Window` implementing the `InputBackend` trait
|
||||||
|
@ -39,50 +40,64 @@ pub struct WinitInputBackend {
|
||||||
seat: Seat,
|
seat: Seat,
|
||||||
input_config: (),
|
input_config: (),
|
||||||
handler: Option<Box<InputHandler<WinitInputBackend> + 'static>>,
|
handler: Option<Box<InputHandler<WinitInputBackend> + 'static>>,
|
||||||
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
||||||
/// graphics backend trait and a corresponding `WinitInputBackend`, which implements
|
/// graphics backend trait and a corresponding `WinitInputBackend`, which implements
|
||||||
/// the `InputBackend` trait
|
/// the `InputBackend` trait
|
||||||
pub fn init() -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> {
|
pub fn init<L>(logger: L) -> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
|
||||||
|
where L: Into<Option<::slog::Logger>>
|
||||||
|
{
|
||||||
init_from_builder(WindowBuilder::new()
|
init_from_builder(WindowBuilder::new()
|
||||||
.with_dimensions(1280, 800)
|
.with_dimensions(1280, 800)
|
||||||
.with_title("Smithay")
|
.with_title("Smithay")
|
||||||
.with_visibility(true))
|
.with_visibility(true), logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
||||||
/// graphics backend trait, from a given `WindowBuilder` struct and a corresponding
|
/// graphics backend trait, from a given `WindowBuilder` struct and a corresponding
|
||||||
/// `WinitInputBackend`, which implements the `InputBackend` trait
|
/// `WinitInputBackend`, which implements the `InputBackend` trait
|
||||||
pub fn init_from_builder(builder: WindowBuilder)
|
pub fn init_from_builder<L>(builder: WindowBuilder, logger: L)
|
||||||
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> {
|
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
|
||||||
|
where L: Into<Option<::slog::Logger>>
|
||||||
|
{
|
||||||
init_from_builder_with_gl_attr(builder,
|
init_from_builder_with_gl_attr(builder,
|
||||||
GlAttributes {
|
GlAttributes {
|
||||||
version: None,
|
version: None,
|
||||||
profile: None,
|
profile: None,
|
||||||
debug: cfg!(debug_assertions),
|
debug: cfg!(debug_assertions),
|
||||||
vsync: true,
|
vsync: true,
|
||||||
})
|
}, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
|
||||||
/// graphics backend trait, from a given `WindowBuilder` struct, as well as given
|
/// graphics backend trait, from a given `WindowBuilder` struct, as well as given
|
||||||
/// `GlAttributes` for further customization of the rendering pipeline and a
|
/// `GlAttributes` for further customization of the rendering pipeline and a
|
||||||
/// corresponding `WinitInputBackend`, which implements the `InputBackend` trait.
|
/// corresponding `WinitInputBackend`, which implements the `InputBackend` trait.
|
||||||
pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttributes)
|
pub fn init_from_builder_with_gl_attr<L>(builder: WindowBuilder, attributes: GlAttributes, logger: L)
|
||||||
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError> {
|
-> Result<(WinitGraphicsBackend, WinitInputBackend), CreationError>
|
||||||
|
where L: Into<Option<::slog::Logger>>
|
||||||
|
{
|
||||||
|
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_winit"));
|
||||||
|
info!(log, "Initializing a winit backend");
|
||||||
|
|
||||||
let events_loop = EventsLoop::new();
|
let events_loop = EventsLoop::new();
|
||||||
let window = Rc::new(builder.build(&events_loop)?);
|
let window = Rc::new(builder.build(&events_loop)?);
|
||||||
|
debug!(log, "Window created");
|
||||||
|
|
||||||
let (native, surface) = if let (Some(conn), Some(window)) =
|
let (native, surface) = if let (Some(conn), Some(window)) =
|
||||||
(get_x11_xconnection(), window.get_xlib_window()) {
|
(get_x11_xconnection(), window.get_xlib_window()) {
|
||||||
|
debug!(log, "Window is backed by X11");
|
||||||
(Native::X11(conn.display as *const _, window), None)
|
(Native::X11(conn.display as *const _, window), None)
|
||||||
} else if let (Some(display), Some(surface)) =
|
} else if let (Some(display), Some(surface)) =
|
||||||
(window.get_wayland_display(), window.get_wayland_client_surface()) {
|
(window.get_wayland_display(), window.get_wayland_client_surface()) {
|
||||||
|
debug!(log, "Window is backed by Wayland");
|
||||||
let (w, h) = window.get_inner_size().unwrap();
|
let (w, h) = window.get_inner_size().unwrap();
|
||||||
let egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32);
|
let egl_surface = wegl::WlEglSurface::new(surface, w as i32, h as i32);
|
||||||
(Native::Wayland(display, egl_surface.ptr() as *const _), Some(egl_surface))
|
(Native::Wayland(display, egl_surface.ptr() as *const _), Some(egl_surface))
|
||||||
} else {
|
} else {
|
||||||
|
error!(log, "Window is backed by an unsupported graphics framework");
|
||||||
return Err(CreationError::NotSupported);
|
return Err(CreationError::NotSupported);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,10 +109,10 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
|
||||||
color_bits: Some(24),
|
color_bits: Some(24),
|
||||||
alpha_bits: Some(8),
|
alpha_bits: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}) {
|
}, log.clone()) {
|
||||||
Ok(context) => context,
|
Ok(context) => context,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("EGLContext creation failed:\n{}", err);
|
error!(log, "EGLContext creation failed:\n {}", err);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +121,7 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
|
||||||
Ok((WinitGraphicsBackend {
|
Ok((WinitGraphicsBackend {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
context: context,
|
context: context,
|
||||||
|
logger: log.new(o!("smithay_winit_component" => "graphics")),
|
||||||
},
|
},
|
||||||
WinitInputBackend {
|
WinitInputBackend {
|
||||||
events_loop: events_loop,
|
events_loop: events_loop,
|
||||||
|
@ -121,6 +137,7 @@ pub fn init_from_builder_with_gl_attr(builder: WindowBuilder, attributes: GlAttr
|
||||||
}),
|
}),
|
||||||
input_config: (),
|
input_config: (),
|
||||||
handler: None,
|
handler: None,
|
||||||
|
logger: log.new(o!("smithay_winit_component" => "input")),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,20 +145,25 @@ impl GraphicsBackend for WinitGraphicsBackend {
|
||||||
type CursorFormat = MouseCursor;
|
type CursorFormat = MouseCursor;
|
||||||
|
|
||||||
fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> {
|
fn set_cursor_position(&mut self, x: u32, y: u32) -> Result<(), ()> {
|
||||||
|
debug!(self.logger, "Setting cursor position to {:?}", (x, y));
|
||||||
self.window.set_cursor_position(x as i32, y as i32)
|
self.window.set_cursor_position(x as i32, y as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor_representation(&mut self, cursor: Self::CursorFormat) {
|
fn set_cursor_representation(&mut self, cursor: Self::CursorFormat) {
|
||||||
|
//Cannot log this one, as `CursorFormat` is not `Debug` and should not be
|
||||||
|
debug!(self.logger, "Changing cursor representation");
|
||||||
self.window.set_cursor(cursor)
|
self.window.set_cursor(cursor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EGLGraphicsBackend for WinitGraphicsBackend {
|
impl EGLGraphicsBackend for WinitGraphicsBackend {
|
||||||
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
fn swap_buffers(&self) -> Result<(), SwapBuffersError> {
|
||||||
|
trace!(self.logger, "Swapping buffers");
|
||||||
self.context.swap_buffers()
|
self.context.swap_buffers()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void {
|
||||||
|
trace!(self.logger, "Getting symbol for {:?}", symbol);
|
||||||
self.context.get_proc_address(symbol)
|
self.context.get_proc_address(symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +178,7 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn make_current(&self) -> Result<(), SwapBuffersError> {
|
unsafe fn make_current(&self) -> Result<(), SwapBuffersError> {
|
||||||
|
debug!(self.logger, "Making context the current one");
|
||||||
self.context.make_current()
|
self.context.make_current()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +471,8 @@ impl InputBackend for WinitInputBackend {
|
||||||
if self.handler.is_some() {
|
if self.handler.is_some() {
|
||||||
self.clear_handler();
|
self.clear_handler();
|
||||||
}
|
}
|
||||||
|
info!(self.logger, "New input handler set.");
|
||||||
|
trace!(self.logger, "Calling on_seat_created with {:?}", self.seat);
|
||||||
handler.on_seat_created(&self.seat);
|
handler.on_seat_created(&self.seat);
|
||||||
self.handler = Some(Box::new(handler));
|
self.handler = Some(Box::new(handler));
|
||||||
}
|
}
|
||||||
|
@ -460,8 +485,10 @@ impl InputBackend for WinitInputBackend {
|
||||||
|
|
||||||
fn clear_handler(&mut self) {
|
fn clear_handler(&mut self) {
|
||||||
if let Some(mut handler) = self.handler.take() {
|
if let Some(mut handler) = self.handler.take() {
|
||||||
|
trace!(self.logger, "Calling on_seat_destroyed with {:?}", self.seat);
|
||||||
handler.on_seat_destroyed(&self.seat);
|
handler.on_seat_destroyed(&self.seat);
|
||||||
}
|
}
|
||||||
|
info!(self.logger, "Removing input handler");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_config(&mut self) -> &mut Self::InputConfig {
|
fn input_config(&mut self) -> &mut Self::InputConfig {
|
||||||
|
@ -484,6 +511,11 @@ impl InputBackend for WinitInputBackend {
|
||||||
let mut closed = false;
|
let mut closed = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// NOTE: This ugly pile of references is here, because rustc could
|
||||||
|
// figure out how to reference all these objects correctly into the
|
||||||
|
// upcoming closure, which is why all are borrowed manually and the
|
||||||
|
// assignments are then moved into the closure to avoid rustc's
|
||||||
|
// wrong interference.
|
||||||
let mut closed_ptr = &mut closed;
|
let mut closed_ptr = &mut closed;
|
||||||
let mut key_counter = &mut self.key_counter;
|
let mut key_counter = &mut self.key_counter;
|
||||||
let mut time_counter = &mut self.time_counter;
|
let mut time_counter = &mut self.time_counter;
|
||||||
|
@ -491,12 +523,14 @@ impl InputBackend for WinitInputBackend {
|
||||||
let window = &self.window;
|
let window = &self.window;
|
||||||
let surface = &self.surface;
|
let surface = &self.surface;
|
||||||
let mut handler = self.handler.as_mut();
|
let mut handler = self.handler.as_mut();
|
||||||
|
let logger = &self.logger;
|
||||||
|
|
||||||
self.events_loop
|
self.events_loop
|
||||||
.poll_events(move |event| match event {
|
.poll_events(move |event| match event {
|
||||||
Event::WindowEvent { event, .. } => {
|
Event::WindowEvent { event, .. } => {
|
||||||
match (event, handler.as_mut()) {
|
match (event, handler.as_mut()) {
|
||||||
(WindowEvent::Resized(x, y), _) => {
|
(WindowEvent::Resized(x, y), _) => {
|
||||||
|
trace!(logger, "Resizing window to {:?}", (x, y));
|
||||||
window.set_inner_size(x, y);
|
window.set_inner_size(x, y);
|
||||||
if let Some(wl_egl_surface) = surface.as_ref() {
|
if let Some(wl_egl_surface) = surface.as_ref() {
|
||||||
wl_egl_surface.resize(x as i32, y as i32, 0, 0);
|
wl_egl_surface.resize(x as i32, y as i32, 0, 0);
|
||||||
|
@ -512,6 +546,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
*key_counter = key_counter.checked_sub(1).unwrap_or(0)
|
*key_counter = key_counter.checked_sub(1).unwrap_or(0)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
trace!(logger, "Calling on_keyboard_key with {:?}", (scancode, state));
|
||||||
handler.on_keyboard_key(seat,
|
handler.on_keyboard_key(seat,
|
||||||
WinitKeyboardInputEvent {
|
WinitKeyboardInputEvent {
|
||||||
time: *time_counter,
|
time: *time_counter,
|
||||||
|
@ -522,6 +557,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
}
|
}
|
||||||
(WindowEvent::MouseMoved { position: (x, y), .. },
|
(WindowEvent::MouseMoved { position: (x, y), .. },
|
||||||
Some(handler)) => {
|
Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_pointer_move_absolute with {:?}", (x, y));
|
||||||
handler.on_pointer_move_absolute(seat,
|
handler.on_pointer_move_absolute(seat,
|
||||||
WinitMouseMovedEvent {
|
WinitMouseMovedEvent {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
|
@ -531,24 +567,32 @@ impl InputBackend for WinitInputBackend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(WindowEvent::MouseWheel { delta, .. }, Some(handler)) => {
|
(WindowEvent::MouseWheel { delta, .. }, Some(handler)) => {
|
||||||
let event = WinitMouseWheelEvent {
|
|
||||||
axis: Axis::Horizontal,
|
|
||||||
time: *time_counter,
|
|
||||||
delta: delta,
|
|
||||||
};
|
|
||||||
match delta {
|
match delta {
|
||||||
MouseScrollDelta::LineDelta(x, y) |
|
MouseScrollDelta::LineDelta(x, y) |
|
||||||
MouseScrollDelta::PixelDelta(x, y) => {
|
MouseScrollDelta::PixelDelta(x, y) => {
|
||||||
if x != 0.0 {
|
if x != 0.0 {
|
||||||
|
let event = WinitMouseWheelEvent {
|
||||||
|
axis: Axis::Horizontal,
|
||||||
|
time: *time_counter,
|
||||||
|
delta: delta,
|
||||||
|
};
|
||||||
|
trace!(logger, "Calling on_pointer_axis for Axis::Horizontal with {:?}", x);
|
||||||
handler.on_pointer_axis(seat, event);
|
handler.on_pointer_axis(seat, event);
|
||||||
}
|
}
|
||||||
if y != 0.0 {
|
if y != 0.0 {
|
||||||
|
let event = WinitMouseWheelEvent {
|
||||||
|
axis: Axis::Vertical,
|
||||||
|
time: *time_counter,
|
||||||
|
delta: delta,
|
||||||
|
};
|
||||||
|
trace!(logger, "Calling on_pointer_axis for Axis::Vertical with {:?}", y);
|
||||||
handler.on_pointer_axis(seat, event);
|
handler.on_pointer_axis(seat, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(WindowEvent::MouseInput { state, button, .. }, Some(handler)) => {
|
(WindowEvent::MouseInput { state, button, .. }, Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_pointer_button with {:?}", (button, state));
|
||||||
handler.on_pointer_button(seat,
|
handler.on_pointer_button(seat,
|
||||||
WinitMouseInputEvent {
|
WinitMouseInputEvent {
|
||||||
time: *time_counter,
|
time: *time_counter,
|
||||||
|
@ -563,6 +607,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
Some(handler)) => {
|
Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_touch_down at {:?}", (x, y));
|
||||||
handler.on_touch_down(seat,
|
handler.on_touch_down(seat,
|
||||||
WinitTouchStartedEvent {
|
WinitTouchStartedEvent {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
|
@ -578,6 +623,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
Some(handler)) => {
|
Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_touch_motion at {:?}", (x, y));
|
||||||
handler.on_touch_motion(seat,
|
handler.on_touch_motion(seat,
|
||||||
WinitTouchMovedEvent {
|
WinitTouchMovedEvent {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
|
@ -593,6 +639,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
Some(handler)) => {
|
Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_touch_motion at {:?}", (x, y));
|
||||||
handler.on_touch_motion(seat,
|
handler.on_touch_motion(seat,
|
||||||
WinitTouchMovedEvent {
|
WinitTouchMovedEvent {
|
||||||
window: window.clone(),
|
window: window.clone(),
|
||||||
|
@ -600,6 +647,7 @@ impl InputBackend for WinitInputBackend {
|
||||||
location: (x, y),
|
location: (x, y),
|
||||||
id: id,
|
id: id,
|
||||||
});
|
});
|
||||||
|
trace!(logger, "Calling on_touch_up");
|
||||||
handler.on_touch_up(seat,
|
handler.on_touch_up(seat,
|
||||||
WinitTouchEndedEvent {
|
WinitTouchEndedEvent {
|
||||||
time: *time_counter,
|
time: *time_counter,
|
||||||
|
@ -612,13 +660,17 @@ impl InputBackend for WinitInputBackend {
|
||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
Some(handler)) => {
|
Some(handler)) => {
|
||||||
|
trace!(logger, "Calling on_touch_cancel");
|
||||||
handler.on_touch_cancel(seat,
|
handler.on_touch_cancel(seat,
|
||||||
WinitTouchCancelledEvent {
|
WinitTouchCancelledEvent {
|
||||||
time: *time_counter,
|
time: *time_counter,
|
||||||
id: id,
|
id: id,
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
(WindowEvent::Closed, _) => *closed_ptr = true,
|
(WindowEvent::Closed, _) => {
|
||||||
|
warn!(logger, "Window closed");
|
||||||
|
*closed_ptr = true;
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
*time_counter += 1;
|
*time_counter += 1;
|
||||||
|
|
Loading…
Reference in New Issue