diff options
Diffstat (limited to 'devices/src/virtio/gpu/backend.rs')
-rw-r--r-- | devices/src/virtio/gpu/backend.rs | 145 |
1 files changed, 107 insertions, 38 deletions
diff --git a/devices/src/virtio/gpu/backend.rs b/devices/src/virtio/gpu/backend.rs index 8f693cc..8dd7806 100644 --- a/devices/src/virtio/gpu/backend.rs +++ b/devices/src/virtio/gpu/backend.rs @@ -76,7 +76,15 @@ trait VirglResource { ); /// Reads from the given rectangle of pixels in the resource to the `dst` slice of memory. - fn read_to_volatile(&mut self, x: u32, y: u32, width: u32, height: u32, dst: VolatileSlice); + fn read_to_volatile( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + dst: VolatileSlice, + dst_stride: u32, + ); } impl VirglResource for GpuRendererResource { @@ -125,12 +133,20 @@ impl VirglResource for GpuRendererResource { } } - fn read_to_volatile(&mut self, x: u32, y: u32, width: u32, height: u32, dst: VolatileSlice) { + fn read_to_volatile( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + dst: VolatileSlice, + dst_stride: u32, + ) { let res = GpuRendererResource::read_to_volatile( self, None, 0, - 0, + dst_stride, 0, /* layer_stride */ Box3::new_2d(x, y, width, height), 0, /* offset */ @@ -278,8 +294,19 @@ impl VirglResource for BackedBuffer { } } - fn read_to_volatile(&mut self, x: u32, y: u32, width: u32, height: u32, dst: VolatileSlice) { - if let Err(e) = self.buffer.read_to_volatile(x, y, width, height, 0, dst) { + fn read_to_volatile( + &mut self, + x: u32, + y: u32, + width: u32, + height: u32, + dst: VolatileSlice, + dst_stride: u32, + ) { + if let Err(e) = self + .buffer + .read_to_volatile(x, y, width, height, 0, dst, dst_stride) + { error!("failed to copy resource: {}", e); } } @@ -292,7 +319,7 @@ impl VirglResource for BackedBuffer { /// failure, or requested data for the given command. pub struct Backend { display: Rc<RefCell<GpuDisplay>>, - device: Device, + device: Option<Device>, renderer: Renderer, resources: Map<u32, Box<dyn VirglResource>>, contexts: Map<u32, RendererContext>, @@ -308,8 +335,11 @@ impl Backend { /// Creates a new backend for virtio-gpu that realizes all commands using the given `device` for /// allocating buffers, `display` for showing the results, and `renderer` for submitting /// rendering commands. + /// + /// If the `device` is None, all buffer allocations will be done internally by the renderer or + /// the display and buffer data is copied as needed. pub fn new( - device: Device, + device: Option<Device>, display: GpuDisplay, renderer: Renderer, gpu_device_socket: VmMemoryControlRequestSocket, @@ -377,30 +407,54 @@ impl Backend { id: u32, width: u32, height: u32, - fourcc: u32, + format: u32, ) -> GpuResponse { if id == 0 { return GpuResponse::ErrInvalidResourceId; } match self.resources.entry(id) { - Entry::Vacant(slot) => { - let res = self.device.create_buffer( - width, - height, - Format::from(fourcc), - Flags::empty().use_scanout(true).use_linear(true), - ); - match res { - Ok(res) => { - slot.insert(Box::from(BackedBuffer::from(res))); - GpuResponse::OkNoData + Entry::Vacant(slot) => match self.device.as_ref() { + Some(device) => match renderer_fourcc(format) { + Some(fourcc) => { + let res = device.create_buffer( + width, + height, + Format::from(fourcc), + Flags::empty().use_scanout(true).use_linear(true), + ); + match res { + Ok(res) => { + slot.insert(Box::from(BackedBuffer::from(res))); + GpuResponse::OkNoData + } + Err(_) => { + error!("failed to create renderer resource {}", fourcc); + GpuResponse::ErrUnspec + } + } + } + None => { + error!( + "unrecognized format can not be converted to fourcc {}", + format + ); + GpuResponse::ErrInvalidParameter } - Err(_) => { - error!("failed to create renderer resource {}", fourcc); - GpuResponse::ErrUnspec + }, + None => { + let res = self.renderer.create_resource_2d(id, width, height, format); + match res { + Ok(res) => { + slot.insert(Box::new(res)); + GpuResponse::OkNoData + } + Err(e) => { + error!("failed to create renderer resource: {}", e); + GpuResponse::ErrUnspec + } } } - } + }, Entry::Occupied(_) => GpuResponse::ErrInvalidResourceId, } } @@ -445,10 +499,10 @@ impl Backend { &mut self, resource_id: u32, surface_id: u32, - x: u32, - y: u32, - width: u32, - height: u32, + _x: u32, + _y: u32, + _width: u32, + _height: u32, ) -> GpuResponse { let resource = match self.resources.get_mut(&resource_id) { Some(r) => r, @@ -461,12 +515,13 @@ impl Backend { } // Import failed, fall back to a copy. - let display = self.display.borrow_mut(); + let mut display = self.display.borrow_mut(); // Prevent overwriting a buffer that is currently being used by the compositor. if display.next_buffer_in_use(surface_id) { return GpuResponse::OkNoData; } - let fb = match display.framebuffer_memory(surface_id) { + + let fb = match display.framebuffer_region(surface_id, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT) { Some(fb) => fb, None => { error!("failed to access framebuffer for surface {}", surface_id); @@ -474,7 +529,14 @@ impl Backend { } }; - resource.read_to_volatile(x, y, width, height, fb); + resource.read_to_volatile( + 0, + 0, + DEFAULT_WIDTH, + DEFAULT_HEIGHT, + fb.as_volatile_slice(), + fb.stride(), + ); display.flip(surface_id); GpuResponse::OkNoData @@ -599,10 +661,16 @@ impl Backend { // Importing failed, so try copying the pixels into the surface's slower shared memory // framebuffer. if let Some(buffer) = resource.buffer() { - if let Some(fb) = self.display.borrow_mut().framebuffer_memory(cursor_surface) { - if let Err(e) = - buffer.read_to_volatile(0, 0, buffer.width(), buffer.height(), 0, fb) - { + if let Some(fb) = self.display.borrow_mut().framebuffer(cursor_surface) { + if let Err(e) = buffer.read_to_volatile( + 0, + 0, + buffer.width(), + buffer.height(), + 0, + fb.as_volatile_slice(), + fb.stride(), + ) { error!("failed to copy resource to cursor: {}", e); return GpuResponse::ErrInvalidParameter; } @@ -619,7 +687,7 @@ impl Backend { pub fn move_cursor(&mut self, x: u32, y: u32) -> GpuResponse { if let Some(cursor_surface) = self.cursor_surface { if let Some(scanout_surface) = self.scanout_surface { - let display = self.display.borrow_mut(); + let mut display = self.display.borrow_mut(); display.set_position(cursor_surface, x, y); display.commit(scanout_surface); } @@ -751,10 +819,11 @@ impl Backend { match self.resources.entry(id) { Entry::Occupied(_) => GpuResponse::ErrInvalidResourceId, Entry::Vacant(slot) => { - if Backend::allocate_using_minigbm(create_args) { + if self.device.is_some() && Backend::allocate_using_minigbm(create_args) { + let device = self.device.as_ref().unwrap(); match renderer_fourcc(create_args.format) { Some(fourcc) => { - let buffer = match self.device.create_buffer( + let buffer = match device.create_buffer( width, height, Format::from(fourcc), @@ -763,7 +832,7 @@ impl Backend { Ok(buffer) => buffer, Err(_) => { // Attempt to allocate the buffer without scanout flag. - match self.device.create_buffer( + match device.create_buffer( width, height, Format::from(fourcc), |