Advance redbear-full Wayland, greeter, and Qt integration
Consolidate the active desktop path around redbear-full while landing the greeter/session stack and the runtime fixes needed to keep Wayland and KWin bring-up moving forward.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# AMD GPU driver port for Redox OS — Phase P2+P5: Display Core + DML2 + TTM
|
||||
# Scope: AMD DC modesetting, DML2 display modeling, TTM memory manager, connector detection.
|
||||
# Full acceleration (compute, video decode) requires Mesa radeonsi backend.
|
||||
# AMD GPU retained display glue path for Redox OS
|
||||
# Scope: bounded Red Bear display glue path for init, connector detection, and modeset.
|
||||
# Imported Linux AMD DC / TTM / amdgpu core trees remain adjacent source under compile triage and
|
||||
# are not part of the default retained build path. Full acceleration still requires broader GPU work
|
||||
# plus Mesa radeonsi backend enablement.
|
||||
|
||||
[source]
|
||||
# Local overlay recipe. The extracted Linux 7.0-rc7 AMDGPU tree lives next to this
|
||||
@@ -20,13 +22,13 @@ DYNAMIC_INIT
|
||||
# Paths
|
||||
AMD_ROOT="${COOKBOOK_SOURCE}/../../amdgpu-source/gpu/drm/amd"
|
||||
AMD_SRC="${AMD_ROOT}"
|
||||
TTM_SRC="${COOKBOOK_SOURCE}/../../amdgpu-source/gpu/drm/ttm"
|
||||
INCLUDES="${COOKBOOK_SOURCE}/../../amdgpu-source/include"
|
||||
LINUX_KPI="${COOKBOOK_ROOT}/local/recipes/drivers/linux-kpi/source/src/c_headers"
|
||||
REDOX_GLUE="${COOKBOOK_SOURCE}"
|
||||
TARGET_CC="${TARGET}-gcc"
|
||||
|
||||
# Compiler flags for AMD driver — DML2 enabled
|
||||
# Compiler flags for the bounded retained AMD path. Legacy AMD DC config defines remain here only
|
||||
# for header compatibility with the adjacent imported Linux source trees.
|
||||
export CFLAGS="-D__redox__ -D__KERNEL__ -DCONFIG_DRM_AMDGPU -DCONFIG_DRM_AMD_DC \
|
||||
-DCONFIG_DRM_AMD_DC_DML2=1 \
|
||||
-DCONFIG_DRM_AMD_DC_FP -DCONFIG_DRM_AMD_ACP \
|
||||
@@ -66,11 +68,20 @@ export CFLAGS="-D__redox__ -D__KERNEL__ -DCONFIG_DRM_AMDGPU -DCONFIG_DRM_AMD_DC
|
||||
"${TARGET_CC}" -c ${CFLAGS} "${REDOX_GLUE}/amdgpu_redox_main.c" -o amdgpu_redox_main.o
|
||||
"${TARGET_CC}" -c ${CFLAGS} "${REDOX_GLUE}/redox_stubs.c" -o redox_stubs.o
|
||||
|
||||
# Stage 2: Compile AMD Display Core (DC) — all display sources including DML/DML2
|
||||
# Each file MUST compile. Any failure is a hard error.
|
||||
# Stage 2: Bounded first-display path
|
||||
#
|
||||
# The current Red Bear AMD display bring-up path does not call into the imported
|
||||
# Linux AMD Display Core tree directly. The live FFI surface comes from the
|
||||
# Red Bear glue layer (`amdgpu_redox_main.c` / `redox_stubs.c`), while the
|
||||
# broad `display/*.c` compile currently drags in optional and unsupported
|
||||
# subtrees such as freesync before the retained path is even proven.
|
||||
#
|
||||
# Keep Stage 2 explicit and intentionally empty until a retained imported
|
||||
# display-source subset is proven necessary by bounded compile triage.
|
||||
DISPLAY_SRCS=""
|
||||
success=0
|
||||
failed=0
|
||||
find "${AMD_SRC}/display/" -name '*.c' | while read -r src; do
|
||||
for src in $DISPLAY_SRCS; do
|
||||
obj=$(basename "${src%.c}.o")
|
||||
if "${TARGET_CC}" -c ${CFLAGS} "$src" -o "$obj" 2>"${obj}.log"; then
|
||||
success=$((success + 1))
|
||||
@@ -81,12 +92,17 @@ find "${AMD_SRC}/display/" -name '*.c' | while read -r src; do
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Stage 2: AMD DC compiled ${success} files, ${failed} failed"
|
||||
echo "Stage 2: bounded AMD display path compiled ${success} imported display files, ${failed} failed"
|
||||
|
||||
# Stage 3: Compile TTM memory manager
|
||||
# Stage 3: Imported TTM path
|
||||
#
|
||||
# The current bounded Red Bear display path uses Rust-side GEM/GTT/ring handling in
|
||||
# `redox-drm`, not the imported Linux TTM stack. Keep this explicit and empty until
|
||||
# the bounded path proves a concrete need for imported TTM code.
|
||||
TTM_SRCS=""
|
||||
success=0
|
||||
failed=0
|
||||
find "${TTM_SRC}/" -name '*.c' | while read -r src; do
|
||||
for src in $TTM_SRCS; do
|
||||
obj=$(basename "${src%.c}.o")
|
||||
if "${TARGET_CC}" -c ${CFLAGS} "$src" -o "$obj" 2>"${obj}.log"; then
|
||||
success=$((success + 1))
|
||||
@@ -97,13 +113,15 @@ find "${TTM_SRC}/" -name '*.c' | while read -r src; do
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "Stage 3: TTM compiled ${success} files, ${failed} failed"
|
||||
echo "Stage 3: bounded imported TTM path compiled ${success} files, ${failed} failed"
|
||||
|
||||
# Stage 4: Compile minimal amdgpu core (enough for display init)
|
||||
CORE_SRCS="amdgpu_device.c amdgpu_drv.c amdgpu_i2c.c amdgpu_atombios.c \
|
||||
amdgpu_atombios_crtc.c amdgpu_bios.c amdgpu_mode.c amdgpu_display.c \
|
||||
amdgpu_fb.c amdgpu_gem.c amdgpu_object.c amdgpu_gmc.c amdgpu_mmhub.c \
|
||||
amdgpu_irq.c amdgpu_ring.c amdgpu_fence.c amdgpu_ttm.c amdgpu_bo_list.c"
|
||||
# Stage 4: Imported amdgpu core path
|
||||
#
|
||||
# The current bounded Red Bear display path uses the custom glue layer for init,
|
||||
# connector enumeration, and modeset, while Rust-side code owns GEM/GTT/ring state.
|
||||
# Keep imported amdgpu core sources out of the retained compile surface until the
|
||||
# bounded path proves a specific dependency on them.
|
||||
CORE_SRCS=""
|
||||
|
||||
success=0
|
||||
failed=0
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
CC = x86_64-unknown-redox-gcc
|
||||
AR = x86_64-unknown-redox-ar
|
||||
|
||||
AMDGPU_SRC ?= ../amdgpu-source/gpu/drm/amd
|
||||
TTM_SRC ?= ../amdgpu-source/gpu/drm/ttm
|
||||
AMDGPU_INCLUDES ?= ../amdgpu-source/include
|
||||
LINUX_KPI ?= ../../drivers/linux-kpi/src/c_headers
|
||||
|
||||
CFLAGS ?= -D__redox__ -D__KERNEL__ -DCONFIG_DRM_AMDGPU -DCONFIG_DRM_AMD_DC \
|
||||
-DCONFIG_DRM_AMD_DC_DML2=1 \
|
||||
-DCONFIG_DRM_AMD_DC_FP -DCONFIG_DRM_AMD_ACP \
|
||||
-I$(LINUX_KPI) \
|
||||
-I. \
|
||||
-I$(AMDGPU_INCLUDES) \
|
||||
-I$(AMDGPU_INCLUDES)/drm \
|
||||
-I$(AMDGPU_SRC)/include \
|
||||
-I$(AMDGPU_SRC)/include/asic_reg \
|
||||
-I$(AMDGPU_SRC)/display \
|
||||
-I$(AMDGPU_SRC)/display/dc \
|
||||
-I$(AMDGPU_SRC)/display/dc/dml \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn20 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn21 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn30 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn301 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn31 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn32 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dcn35 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dml2_0 \
|
||||
-I$(AMDGPU_SRC)/display/dc/dml2_0/dml21 \
|
||||
-I$(AMDGPU_SRC)/display/dmub \
|
||||
-I$(AMDGPU_SRC)/display/modules \
|
||||
-I$(AMDGPU_SRC)/display/modules/freesync \
|
||||
-I$(AMDGPU_SRC)/display/modules/color \
|
||||
-I$(AMDGPU_SRC)/display/modules/info_packet \
|
||||
-I$(AMDGPU_SRC)/display/modules/power \
|
||||
-I$(AMDGPU_SRC)/pm/swsmu \
|
||||
-I$(AMDGPU_SRC)/pm/swsmu/inc \
|
||||
-I$(AMDGPU_SRC)/pm/powerplay \
|
||||
-I$(AMDGPU_SRC)/pm/powerplay/inc \
|
||||
-I$(AMDGPU_SRC)/pm/powerplay/hwmgr \
|
||||
-fPIC -O2 -Wall -Wno-unused-function -Wno-unused-variable \
|
||||
-Wno-address-of-packed-member -Wno-initializer-overrides
|
||||
|
||||
LDFLAGS ?= -shared
|
||||
LDLIBS ?= -lredox_driver_sys -llinux_kpi -lm -lpthread
|
||||
|
||||
GLUE_OBJS := redox_stubs.o amdgpu_redox_main.o
|
||||
CORE_SRCS := \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_device.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_drv.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_i2c.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_atombios.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_atombios_crtc.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_bios.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_mode.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_display.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_fb.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_gem.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_object.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_gmc.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_mmhub.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_irq.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_ring.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_fence.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_ttm.c \
|
||||
$(AMDGPU_SRC)/amdgpu/amdgpu_bo_list.c
|
||||
CORE_OBJS := $(patsubst %.c,%.o,$(notdir $(CORE_SRCS)))
|
||||
DISPLAY_SRCS := $(shell find $(AMDGPU_SRC)/display -name '*.c')
|
||||
DISPLAY_OBJS := $(patsubst %.c,%.o,$(notdir $(DISPLAY_SRCS)))
|
||||
TTM_SRCS := $(shell find $(TTM_SRC) -name '*.c')
|
||||
TTM_OBJS := $(patsubst %.c,%.o,$(notdir $(TTM_SRCS)))
|
||||
|
||||
ALL_OBJS := $(GLUE_OBJS) $(DISPLAY_OBJS) $(TTM_OBJS) $(CORE_OBJS)
|
||||
|
||||
.PHONY: all clean check display core ttm
|
||||
|
||||
all: libamdgpu_dc_redox.so
|
||||
|
||||
libamdgpu_dc_redox.so: $(GLUE_OBJS)
|
||||
@set -e; \
|
||||
success=0; failed=0; \
|
||||
for src in $(DISPLAY_SRCS); do \
|
||||
obj=$$(basename "$${src%.c}.o"); \
|
||||
if $(CC) -c $(CFLAGS) "$$src" -o "$$obj"; then \
|
||||
success=$$((success + 1)); \
|
||||
else \
|
||||
failed=$$((failed + 1)); \
|
||||
echo "ERROR: failed to compile $$src"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done; \
|
||||
for src in $(TTM_SRCS); do \
|
||||
obj=$$(basename "$${src%.c}.o"); \
|
||||
if $(CC) -c $(CFLAGS) "$$src" -o "$$obj"; then \
|
||||
success=$$((success + 1)); \
|
||||
else \
|
||||
failed=$$((failed + 1)); \
|
||||
echo "ERROR: failed to compile $$src"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done; \
|
||||
for src in $(CORE_SRCS); do \
|
||||
if [ -f "$$src" ]; then \
|
||||
obj=$$(basename "$${src%.c}.o"); \
|
||||
if $(CC) -c $(CFLAGS) "$$src" -o "$$obj"; then \
|
||||
success=$$((success + 1)); \
|
||||
else \
|
||||
failed=$$((failed + 1)); \
|
||||
echo "ERROR: failed to compile $$src"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
fi; \
|
||||
done; \
|
||||
echo "AMD DC: compiled $$success files successfully"; \
|
||||
$(CC) $(LDFLAGS) -o $@ $$(find . -maxdepth 1 -name '*.o' -size +0c) $(LDLIBS)
|
||||
|
||||
redox_stubs.o: redox_stubs.c redox_glue.h
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
amdgpu_redox_main.o: amdgpu_redox_main.c redox_glue.h
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
check: $(GLUE_OBJS)
|
||||
$(CC) -fsyntax-only $(CFLAGS) amdgpu_redox_main.c
|
||||
$(CC) -fsyntax-only $(CFLAGS) redox_stubs.c
|
||||
|
||||
clean:
|
||||
rm -f *.o libamdgpu_dc_redox.so
|
||||
@@ -5,6 +5,7 @@ const LIB_NAME: &str = "libamdgpu_dc_redox.so";
|
||||
const ENV_HINTS: &[&str] = &[
|
||||
"AMDGPU_DC_LIB_DIR",
|
||||
"COOKBOOK_STAGE",
|
||||
"COOKBOOK_SYSROOT",
|
||||
"REDOX_SYSROOT",
|
||||
"SYSROOT",
|
||||
"TARGET_SYSROOT",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashSet, VecDeque};
|
||||
use std::mem::size_of;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -286,6 +286,7 @@ enum NodeKind {
|
||||
struct Handle {
|
||||
node: NodeKind,
|
||||
response: Vec<u8>,
|
||||
event_queue: VecDeque<Vec<u8>>,
|
||||
mapped_gem: Option<GemHandle>,
|
||||
mapped_gem_refs: usize,
|
||||
owned_fbs: Vec<u32>,
|
||||
@@ -548,6 +549,7 @@ impl DrmScheme {
|
||||
Handle {
|
||||
node,
|
||||
response: Vec::new(),
|
||||
event_queue: VecDeque::new(),
|
||||
mapped_gem: None,
|
||||
mapped_gem_refs: 0,
|
||||
owned_fbs: Vec::new(),
|
||||
@@ -636,8 +638,34 @@ impl DrmScheme {
|
||||
|
||||
pub fn handle_driver_event(&mut self, event: DriverEvent) {
|
||||
match event {
|
||||
DriverEvent::Vblank { crtc_id, count } => self.retire_vblank(crtc_id, count),
|
||||
DriverEvent::Hotplug { .. } => {}
|
||||
DriverEvent::Vblank { crtc_id, count } => {
|
||||
self.retire_vblank(crtc_id, count);
|
||||
self.queue_card_event(format!("vblank:{crtc_id}:{count}\n").into_bytes());
|
||||
}
|
||||
DriverEvent::Hotplug { connector_id } => self.queue_hotplug_event(connector_id),
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_card_event(&mut self, payload: Vec<u8>) {
|
||||
for handle in self.handles.values_mut() {
|
||||
if let NodeKind::Card = handle.node {
|
||||
handle.event_queue.push_back(payload.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_hotplug_event(&mut self, connector_id: u32) {
|
||||
let payload = format!("hotplug:{}\n", connector_id).into_bytes();
|
||||
for handle in self.handles.values_mut() {
|
||||
match handle.node {
|
||||
NodeKind::Card => {
|
||||
handle.event_queue.push_back(payload.clone());
|
||||
}
|
||||
NodeKind::Connector(id) if id == connector_id => {
|
||||
handle.event_queue.push_back(payload.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1394,9 +1422,19 @@ impl SchemeBlockMut for DrmScheme {
|
||||
|
||||
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get_mut(&id).ok_or_else(|| Error::new(EBADF))?;
|
||||
let len = handle.response.len().min(buf.len());
|
||||
buf[..len].copy_from_slice(&handle.response[..len]);
|
||||
Ok(Some(len))
|
||||
if !handle.response.is_empty() {
|
||||
let len = handle.response.len().min(buf.len());
|
||||
buf[..len].copy_from_slice(&handle.response[..len]);
|
||||
return Ok(Some(len));
|
||||
}
|
||||
|
||||
if let Some(event) = handle.event_queue.pop_front() {
|
||||
let len = event.len().min(buf.len());
|
||||
buf[..len].copy_from_slice(&event[..len]);
|
||||
return Ok(Some(len));
|
||||
}
|
||||
|
||||
Ok(Some(0))
|
||||
}
|
||||
|
||||
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
|
||||
@@ -1428,7 +1466,11 @@ impl SchemeBlockMut for DrmScheme {
|
||||
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
|
||||
let handle = self.handles.get(&id).ok_or_else(|| Error::new(EBADF))?;
|
||||
stat.st_mode = MODE_FILE | 0o666;
|
||||
stat.st_size = handle.response.len() as u64;
|
||||
stat.st_size = if !handle.response.is_empty() {
|
||||
handle.response.len() as u64
|
||||
} else {
|
||||
handle.event_queue.front().map(|payload| payload.len()).unwrap_or(0) as u64
|
||||
};
|
||||
stat.st_blksize = 4096;
|
||||
Ok(Some(0))
|
||||
}
|
||||
@@ -1441,9 +1483,14 @@ impl SchemeBlockMut for DrmScheme {
|
||||
Err(Error::new(EOPNOTSUPP))
|
||||
}
|
||||
|
||||
fn fevent(&mut self, id: usize, _flags: EventFlags) -> Result<Option<EventFlags>> {
|
||||
let _ = self.handles.get(&id).ok_or_else(|| Error::new(EBADF))?;
|
||||
Ok(Some(EventFlags::empty()))
|
||||
fn fevent(&mut self, id: usize, flags: EventFlags) -> Result<Option<EventFlags>> {
|
||||
let handle = self.handles.get(&id).ok_or_else(|| Error::new(EBADF))?;
|
||||
let readiness = if handle.event_queue.is_empty() {
|
||||
EventFlags::empty()
|
||||
} else {
|
||||
flags & EventFlags::EVENT_READ
|
||||
};
|
||||
Ok(Some(readiness))
|
||||
}
|
||||
|
||||
fn close(&mut self, id: usize) -> Result<Option<usize>> {
|
||||
@@ -1785,6 +1832,13 @@ mod tests {
|
||||
scheme.open("card0", 0, 0, 0).unwrap().unwrap()
|
||||
}
|
||||
|
||||
fn open_connector(scheme: &mut DrmScheme, connector_id: u32) -> usize {
|
||||
scheme
|
||||
.open(&format!("card0Connector/{connector_id}"), 0, 0, 0)
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn write_ioctl<T>(scheme: &mut DrmScheme, id: usize, request: usize, payload: &T) -> Result<usize> {
|
||||
let mut buf = request.to_le_bytes().to_vec();
|
||||
buf.extend_from_slice(&bytes_of(payload));
|
||||
@@ -1998,6 +2052,7 @@ mod tests {
|
||||
#[test]
|
||||
fn non_vblank_driver_event_does_not_retire_pending_page_flip() {
|
||||
let mut scheme = DrmScheme::new(Arc::new(FakeDriver::new(false)));
|
||||
let card = open_card(&mut scheme);
|
||||
|
||||
scheme.fb_registry.insert(
|
||||
9,
|
||||
@@ -2015,6 +2070,73 @@ mod tests {
|
||||
|
||||
assert_eq!(scheme.pending_flip_fb.get(&1), Some(&(2, 9)));
|
||||
assert!(scheme.fb_registry.contains_key(&9));
|
||||
assert_eq!(
|
||||
scheme.fevent(card, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::EVENT_READ)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hotplug_event_is_readable_from_card_handle() {
|
||||
let mut scheme = DrmScheme::new(Arc::new(FakeDriver::new(false)));
|
||||
let card = open_card(&mut scheme);
|
||||
|
||||
scheme.handle_driver_event(DriverEvent::Hotplug { connector_id: 7 });
|
||||
|
||||
assert_eq!(
|
||||
scheme.fevent(card, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::EVENT_READ)
|
||||
);
|
||||
|
||||
let mut buf = [0u8; 32];
|
||||
let len = scheme.read(card, &mut buf).unwrap().unwrap();
|
||||
assert_eq!(&buf[..len], b"hotplug:7\n");
|
||||
assert_eq!(
|
||||
scheme.fevent(card, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::empty())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hotplug_event_targets_matching_connector_handle_only() {
|
||||
let mut scheme = DrmScheme::new(Arc::new(FakeDriver::new(false)));
|
||||
let connector_a = open_connector(&mut scheme, 1);
|
||||
let connector_b = open_connector(&mut scheme, 2);
|
||||
|
||||
scheme.handle_driver_event(DriverEvent::Hotplug { connector_id: 2 });
|
||||
|
||||
assert_eq!(
|
||||
scheme.fevent(connector_a, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::empty())
|
||||
);
|
||||
assert_eq!(
|
||||
scheme.fevent(connector_b, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::EVENT_READ)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vblank_event_is_readable_from_card_handle() {
|
||||
let mut scheme = DrmScheme::new(Arc::new(FakeDriver::new(false)));
|
||||
let card = open_card(&mut scheme);
|
||||
|
||||
scheme.handle_driver_event(DriverEvent::Vblank {
|
||||
crtc_id: 4,
|
||||
count: 12,
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
scheme.fevent(card, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::EVENT_READ)
|
||||
);
|
||||
|
||||
let mut buf = [0u8; 32];
|
||||
let len = scheme.read(card, &mut buf).unwrap().unwrap();
|
||||
assert_eq!(&buf[..len], b"vblank:4:12\n");
|
||||
assert_eq!(
|
||||
scheme.fevent(card, EventFlags::EVENT_READ).unwrap(),
|
||||
Some(EventFlags::empty())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user