gfx: add GfxStagingBuffer
This commit is contained in:
parent
1462933ef4
commit
3619a51fbd
11 changed files with 215 additions and 43 deletions
|
|
@ -503,6 +503,17 @@ pub trait AsyncShmGfxTextureCallback {
|
|||
fn completed(self: Rc<Self>, res: Result<(), GfxError>);
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
StagingBufferUsecase: u32;
|
||||
STAGING_UPLOAD = 1 << 0,
|
||||
STAGING_DOWNLOAD = 1 << 1,
|
||||
}
|
||||
|
||||
pub trait GfxStagingBuffer {
|
||||
fn size(&self) -> usize;
|
||||
fn into_any(self: Rc<Self>) -> Rc<dyn Any>;
|
||||
}
|
||||
|
||||
pub trait AsyncShmGfxTextureUploadCancellable {
|
||||
fn cancel(&self, id: u64);
|
||||
}
|
||||
|
|
@ -539,8 +550,13 @@ impl ShmMemory for Vec<Cell<u8>> {
|
|||
}
|
||||
|
||||
pub trait AsyncShmGfxTexture: GfxTexture {
|
||||
fn staging_size(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
staging: &Rc<dyn GfxStagingBuffer>,
|
||||
callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
damage: Region,
|
||||
|
|
@ -605,6 +621,25 @@ pub trait GfxContext: Debug {
|
|||
) -> Result<Rc<dyn GfxFramebuffer>, GfxError>;
|
||||
|
||||
fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>>;
|
||||
|
||||
fn create_staging_buffer(
|
||||
&self,
|
||||
size: usize,
|
||||
usecase: StagingBufferUsecase,
|
||||
) -> Rc<dyn GfxStagingBuffer> {
|
||||
let _ = usecase;
|
||||
struct Dummy(usize);
|
||||
impl GfxStagingBuffer for Dummy {
|
||||
fn size(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
Rc::new(Dummy(size))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use {
|
|||
crate::{
|
||||
format::Format,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxError, GfxTexture, PendingShmUpload,
|
||||
ShmGfxTexture, ShmMemory,
|
||||
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxError, GfxStagingBuffer, GfxTexture,
|
||||
PendingShmUpload, ShmGfxTexture, ShmMemory,
|
||||
},
|
||||
gfx_apis::gl::{
|
||||
gl::texture::GlTexture,
|
||||
|
|
@ -100,6 +100,7 @@ impl ShmGfxTexture for Texture {
|
|||
impl AsyncShmGfxTexture for Texture {
|
||||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
_staging: &Rc<dyn GfxStagingBuffer>,
|
||||
_callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
_damage: Region,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ use {
|
|||
format::Format,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage,
|
||||
ResetStatus, ShmGfxTexture,
|
||||
GfxStagingBuffer, ResetStatus, ShmGfxTexture, StagingBufferUsecase, STAGING_DOWNLOAD,
|
||||
STAGING_UPLOAD,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
image::VulkanImageMemory, instance::VulkanInstance, renderer::VulkanRenderer,
|
||||
|
|
@ -203,6 +204,10 @@ pub enum VulkanError {
|
|||
AsyncCopyToStaging(#[source] ReadWriteJobError),
|
||||
#[error("The async shm texture is busy")]
|
||||
AsyncCopyBusy,
|
||||
#[error("The staging buffer is busy")]
|
||||
StagingBufferBusy,
|
||||
#[error("The staging buffer does not support uploads")]
|
||||
StagingBufferNoUpload,
|
||||
}
|
||||
|
||||
impl From<VulkanError> for GfxError {
|
||||
|
|
@ -330,6 +335,18 @@ impl GfxContext for Context {
|
|||
fn sync_obj_ctx(&self) -> Option<&Rc<SyncObjCtx>> {
|
||||
Some(&self.0.device.sync_ctx)
|
||||
}
|
||||
|
||||
fn create_staging_buffer(
|
||||
&self,
|
||||
size: usize,
|
||||
usecase: StagingBufferUsecase,
|
||||
) -> Rc<dyn GfxStagingBuffer> {
|
||||
let upload = usecase.contains(STAGING_UPLOAD);
|
||||
let download = usecase.contains(STAGING_DOWNLOAD);
|
||||
self.0
|
||||
.device
|
||||
.create_staging_shell(size as u64, upload, download)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Context {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use {
|
|||
gfx_api::{
|
||||
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback,
|
||||
AsyncShmGfxTextureUploadCancellable, GfxApiOpt, GfxError, GfxFramebuffer, GfxImage,
|
||||
GfxTexture, PendingShmUpload, ReleaseSync, ShmGfxTexture, ShmMemory, SyncFile,
|
||||
GfxStagingBuffer, GfxTexture, PendingShmUpload, ReleaseSync, ShmGfxTexture, ShmMemory,
|
||||
SyncFile,
|
||||
},
|
||||
gfx_apis::vulkan::{
|
||||
allocator::VulkanAllocation, device::VulkanDevice, format::VulkanModifierLimits,
|
||||
|
|
@ -575,8 +576,16 @@ impl ShmGfxTexture for VulkanImage {
|
|||
}
|
||||
|
||||
impl AsyncShmGfxTexture for VulkanImage {
|
||||
fn staging_size(&self) -> usize {
|
||||
let VulkanImageMemory::Internal(shm) = &self.ty else {
|
||||
unreachable!();
|
||||
};
|
||||
shm.size as _
|
||||
}
|
||||
|
||||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
staging: &Rc<dyn GfxStagingBuffer>,
|
||||
callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
damage: Region,
|
||||
|
|
@ -584,7 +593,8 @@ impl AsyncShmGfxTexture for VulkanImage {
|
|||
let VulkanImageMemory::Internal(shm) = &self.ty else {
|
||||
unreachable!();
|
||||
};
|
||||
let pending = shm.async_upload(&self, &mem, damage, callback)?;
|
||||
let staging = staging.clone().into_vk(&self.renderer.device.device);
|
||||
let pending = shm.async_upload(&self, staging, &mem, damage, callback)?;
|
||||
Ok(pending)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use {
|
|||
fence::VulkanFence,
|
||||
image::{QueueFamily, QueueState, QueueTransfer, VulkanImage, VulkanImageMemory},
|
||||
renderer::{image_barrier, VulkanRenderer},
|
||||
staging::VulkanStagingBuffer,
|
||||
staging::{VulkanStagingBuffer, VulkanStagingShell},
|
||||
VulkanError,
|
||||
},
|
||||
rect::{Rect, Region},
|
||||
|
|
@ -55,7 +55,7 @@ pub struct VulkanShmImageAsyncData {
|
|||
pub(super) busy: Cell<bool>,
|
||||
pub(super) io_job: Cell<Option<Box<IoUploadJob>>>,
|
||||
pub(super) copy_job: Cell<Option<Box<CopyUploadJob>>>,
|
||||
pub(super) staging: CloneCell<Option<Rc<VulkanStagingBuffer>>>,
|
||||
pub(super) staging: CloneCell<Option<Rc<VulkanStagingShell>>>,
|
||||
pub(super) callback: Cell<Option<Rc<dyn AsyncShmGfxTextureCallback>>>,
|
||||
pub(super) callback_id: Cell<u64>,
|
||||
pub(super) regions: RefCell<Vec<BufferImageCopy2<'static>>>,
|
||||
|
|
@ -320,6 +320,7 @@ async fn await_upload(
|
|||
impl VulkanShmImageAsyncData {
|
||||
fn complete(&self, result: Result<(), VulkanError>) {
|
||||
self.busy.set(false);
|
||||
self.staging.take().unwrap().busy.set(false);
|
||||
if let Some(cb) = self.callback.take() {
|
||||
cb.completed(result.map_err(|e| e.into()));
|
||||
}
|
||||
|
|
@ -330,12 +331,13 @@ impl VulkanShmImage {
|
|||
pub fn async_upload(
|
||||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
staging: Rc<VulkanStagingShell>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
damage: Region,
|
||||
callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
) -> Result<Option<PendingShmUpload>, VulkanError> {
|
||||
let data = self.async_data.as_ref().unwrap();
|
||||
let res = self.try_async_upload(img, data, client_mem, damage);
|
||||
let res = self.try_async_upload(img, staging, data, client_mem, damage);
|
||||
match res {
|
||||
Ok(()) => {
|
||||
let id = img.renderer.allocate_point();
|
||||
|
|
@ -350,6 +352,7 @@ impl VulkanShmImage {
|
|||
fn try_async_upload(
|
||||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
staging: Rc<VulkanStagingShell>,
|
||||
data: &VulkanShmImageAsyncData,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
mut damage: Region,
|
||||
|
|
@ -357,11 +360,19 @@ impl VulkanShmImage {
|
|||
if data.busy.get() {
|
||||
return Err(VulkanError::AsyncCopyBusy);
|
||||
}
|
||||
if staging.busy.get() {
|
||||
return Err(VulkanError::StagingBufferBusy);
|
||||
}
|
||||
if !staging.upload {
|
||||
return Err(VulkanError::StagingBufferNoUpload);
|
||||
}
|
||||
if self.size > client_mem.len() as u64 {
|
||||
return Err(VulkanError::InvalidBufferSize);
|
||||
}
|
||||
data.busy.set(true);
|
||||
data.data_copied.set(false);
|
||||
staging.busy.set(true);
|
||||
data.staging.set(Some(staging.clone()));
|
||||
if img.contents_are_undefined.get() {
|
||||
damage = Region::new2(Rect::new_sized(0, 0, img.width as _, img.height as _).unwrap());
|
||||
}
|
||||
|
|
@ -416,27 +427,22 @@ impl VulkanShmImage {
|
|||
|
||||
self.async_release_from_gfx_queue(img, data)?;
|
||||
|
||||
if let Some(staging) = data.staging.get() {
|
||||
if let Some(staging) = staging.staging.get() {
|
||||
return self.async_upload_initiate_copy(img, data, &staging, copies, client_mem);
|
||||
}
|
||||
|
||||
let img2 = img.clone();
|
||||
let client_mem = client_mem.clone();
|
||||
img.renderer.device.create_shm_staging(
|
||||
&img.renderer,
|
||||
&data.cpu,
|
||||
self.size,
|
||||
true,
|
||||
false,
|
||||
move |res| {
|
||||
img.renderer
|
||||
.device
|
||||
.fill_staging_shell(&img.renderer, &data.cpu, staging, move |res| {
|
||||
let VulkanImageMemory::Internal(shm) = &img2.ty else {
|
||||
unreachable!();
|
||||
};
|
||||
if let Err(e) = shm.async_upload_after_allocation(&img2, &client_mem, res) {
|
||||
shm.async_data.as_ref().unwrap().complete(Err(e));
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn async_release_from_gfx_queue(
|
||||
|
|
@ -532,11 +538,10 @@ impl VulkanShmImage {
|
|||
&self,
|
||||
img: &Rc<VulkanImage>,
|
||||
client_mem: &Rc<dyn ShmMemory>,
|
||||
res: Result<VulkanStagingBuffer, VulkanError>,
|
||||
res: Result<Rc<VulkanStagingBuffer>, VulkanError>,
|
||||
) -> Result<(), VulkanError> {
|
||||
let staging = Rc::new(res?);
|
||||
let staging = res?;
|
||||
let data = self.async_data.as_ref().unwrap();
|
||||
data.staging.set(Some(staging.clone()));
|
||||
let copies = &*data.regions.borrow();
|
||||
self.async_upload_initiate_copy(img, data, &staging, copies, client_mem)
|
||||
}
|
||||
|
|
@ -637,7 +642,7 @@ impl VulkanShmImage {
|
|||
}
|
||||
img.renderer.check_defunct()?;
|
||||
let regions = &*data.regions.borrow();
|
||||
let staging = data.staging.get().unwrap();
|
||||
let staging = data.staging.get().unwrap().staging.get().unwrap();
|
||||
staging.upload(|_, _| ())?;
|
||||
let Some((cmd, fence, sync_file, point)) =
|
||||
self.submit_buffer_to_image_copy(img, &staging, regions, true)?
|
||||
|
|
|
|||
|
|
@ -1,17 +1,24 @@
|
|||
use {
|
||||
crate::{
|
||||
cpu_worker::CpuWorker,
|
||||
gfx_api::GfxStagingBuffer,
|
||||
gfx_apis::vulkan::{
|
||||
allocator::{VulkanAllocation, VulkanAllocator},
|
||||
device::VulkanDevice,
|
||||
renderer::VulkanRenderer,
|
||||
VulkanError,
|
||||
},
|
||||
utils::on_drop::{OnDrop, OnDrop2},
|
||||
utils::{
|
||||
clonecell::CloneCell,
|
||||
on_drop::{OnDrop, OnDrop2},
|
||||
},
|
||||
},
|
||||
ash::{
|
||||
vk::{Buffer, BufferCreateInfo, BufferUsageFlags, MappedMemoryRange},
|
||||
Device,
|
||||
},
|
||||
ash::vk::{Buffer, BufferCreateInfo, BufferUsageFlags, MappedMemoryRange},
|
||||
gpu_alloc::UsageFlags,
|
||||
std::rc::Rc,
|
||||
std::{any::Any, cell::Cell, rc::Rc},
|
||||
};
|
||||
|
||||
pub struct VulkanStagingBuffer {
|
||||
|
|
@ -22,6 +29,22 @@ pub struct VulkanStagingBuffer {
|
|||
}
|
||||
|
||||
impl VulkanDevice {
|
||||
pub(super) fn create_staging_shell(
|
||||
self: &Rc<Self>,
|
||||
size: u64,
|
||||
upload: bool,
|
||||
download: bool,
|
||||
) -> Rc<VulkanStagingShell> {
|
||||
Rc::new(VulkanStagingShell {
|
||||
device: self.clone(),
|
||||
staging: Default::default(),
|
||||
size,
|
||||
download,
|
||||
upload,
|
||||
busy: Cell::new(false),
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn create_staging_buffer(
|
||||
self: &Rc<Self>,
|
||||
allocator: &Rc<VulkanAllocator>,
|
||||
|
|
@ -51,17 +74,15 @@ impl VulkanDevice {
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn create_shm_staging(
|
||||
pub(super) fn fill_staging_shell(
|
||||
self: &Rc<Self>,
|
||||
renderer: &Rc<VulkanRenderer>,
|
||||
cpu: &Rc<CpuWorker>,
|
||||
size: u64,
|
||||
upload: bool,
|
||||
download: bool,
|
||||
cb: impl FnOnce(Result<VulkanStagingBuffer, VulkanError>) + 'static,
|
||||
shell: Rc<VulkanStagingShell>,
|
||||
cb: impl FnOnce(Result<Rc<VulkanStagingBuffer>, VulkanError>) + 'static,
|
||||
) -> Result<(), VulkanError> {
|
||||
let (vk_usage, usage) = get_usage(upload, download, false);
|
||||
let buffer = self.create_buffer(size, vk_usage)?;
|
||||
let (vk_usage, usage) = get_usage(shell.upload, shell.download, false);
|
||||
let buffer = self.create_buffer(shell.size, vk_usage)?;
|
||||
let memory_requirements = unsafe { self.device.get_buffer_memory_requirements(buffer) };
|
||||
let slf = self.clone();
|
||||
let destroy_buffer =
|
||||
|
|
@ -77,12 +98,14 @@ impl VulkanDevice {
|
|||
res.map_err(VulkanError::BindBufferMemory)?;
|
||||
}
|
||||
destroy_buffer.forget();
|
||||
Ok(VulkanStagingBuffer {
|
||||
let buffer = Rc::new(VulkanStagingBuffer {
|
||||
device: slf.clone(),
|
||||
allocation,
|
||||
buffer,
|
||||
size,
|
||||
})
|
||||
size: shell.size,
|
||||
});
|
||||
shell.staging.set(Some(buffer.clone()));
|
||||
Ok(buffer)
|
||||
};
|
||||
renderer.shm_allocator.async_alloc(
|
||||
renderer,
|
||||
|
|
@ -159,3 +182,43 @@ impl Drop for VulkanStagingBuffer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct VulkanStagingShell {
|
||||
pub(super) device: Rc<VulkanDevice>,
|
||||
pub(super) staging: CloneCell<Option<Rc<VulkanStagingBuffer>>>,
|
||||
pub(super) size: u64,
|
||||
pub(super) download: bool,
|
||||
pub(super) upload: bool,
|
||||
pub(super) busy: Cell<bool>,
|
||||
}
|
||||
|
||||
impl GfxStagingBuffer for VulkanStagingShell {
|
||||
fn size(&self) -> usize {
|
||||
self.size as _
|
||||
}
|
||||
|
||||
fn into_any(self: Rc<Self>) -> Rc<dyn Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl VulkanStagingShell {
|
||||
fn assert_device(&self, device: &Device) {
|
||||
assert_eq!(
|
||||
self.device.device.handle(),
|
||||
device.handle(),
|
||||
"Mixed vulkan device use"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn GfxStagingBuffer {
|
||||
pub(super) fn into_vk(self: Rc<Self>, device: &Device) -> Rc<VulkanStagingShell> {
|
||||
let shell: Rc<VulkanStagingShell> = self
|
||||
.into_any()
|
||||
.downcast()
|
||||
.expect("Non-vulkan staging buffer passed into vulkan");
|
||||
shell.assert_device(device);
|
||||
shell
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ impl WlBuffer {
|
|||
WlBufferStorage::Shm { .. } => {
|
||||
return match surface {
|
||||
Some(s) => {
|
||||
s.shm_staging.take();
|
||||
s.shm_textures.back().tex.take();
|
||||
s.shm_textures.front().tex.take().is_some()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ use {
|
|||
drm_feedback::DrmFeedback,
|
||||
fixed::Fixed,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, ReleaseSync, SampleRect,
|
||||
SyncFile,
|
||||
AsyncShmGfxTexture, BufferResv, BufferResvUser, GfxError, GfxStagingBuffer,
|
||||
ReleaseSync, SampleRect, SyncFile,
|
||||
},
|
||||
ifs::{
|
||||
wl_buffer::WlBuffer,
|
||||
|
|
@ -276,6 +276,7 @@ pub struct WlSurface {
|
|||
pub buffer_abs_pos: Cell<Rect>,
|
||||
pub need_extents_update: Cell<bool>,
|
||||
pub buffer: CloneCell<Option<Rc<SurfaceBuffer>>>,
|
||||
pub shm_staging: CloneCell<Option<Rc<dyn GfxStagingBuffer>>>,
|
||||
pub shm_textures: DoubleBuffered<SurfaceShmTexture>,
|
||||
pub buf_x: NumCell<i32>,
|
||||
pub buf_y: NumCell<i32>,
|
||||
|
|
@ -593,6 +594,7 @@ impl WlSurface {
|
|||
buffer_abs_pos: Cell::new(Default::default()),
|
||||
need_extents_update: Default::default(),
|
||||
buffer: Default::default(),
|
||||
shm_staging: Default::default(),
|
||||
shm_textures: DoubleBuffered::new(DamageQueue::new().map(|damage| SurfaceShmTexture {
|
||||
tex: Default::default(),
|
||||
damage,
|
||||
|
|
@ -1327,6 +1329,7 @@ impl WlSurface {
|
|||
}
|
||||
|
||||
pub fn reset_shm_textures(&self) {
|
||||
self.shm_staging.take();
|
||||
for tex in &*self.shm_textures {
|
||||
tex.tex.take();
|
||||
tex.damage.clear();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use {
|
||||
crate::{
|
||||
gfx_api::{AsyncShmGfxTextureCallback, GfxError, PendingShmUpload},
|
||||
gfx_api::{AsyncShmGfxTextureCallback, GfxError, PendingShmUpload, STAGING_UPLOAD},
|
||||
ifs::{
|
||||
wl_buffer::WlBufferStorage,
|
||||
wl_surface::{PendingState, WlSurface, WlSurfaceError},
|
||||
|
|
@ -459,8 +459,28 @@ fn schedule_async_upload(
|
|||
back_tex
|
||||
}
|
||||
};
|
||||
let mut staging_opt = surface.shm_staging.get();
|
||||
if let Some(staging) = &staging_opt {
|
||||
if staging.size() != back_tex.staging_size() {
|
||||
staging_opt = None;
|
||||
}
|
||||
}
|
||||
let staging = match staging_opt {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
let s = surface
|
||||
.client
|
||||
.state
|
||||
.render_ctx
|
||||
.get()
|
||||
.ok_or(WlSurfaceError::NoRenderContext)?
|
||||
.create_staging_buffer(back_tex.staging_size(), STAGING_UPLOAD);
|
||||
surface.shm_staging.set(Some(s.clone()));
|
||||
s
|
||||
}
|
||||
};
|
||||
back_tex
|
||||
.async_upload(node_ref.clone(), mem.clone(), back.damage.get())
|
||||
.async_upload(&staging, node_ref.clone(), mem.clone(), back.damage.get())
|
||||
.map_err(WlSurfaceError::PrepareAsyncUpload)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use {
|
|||
gfx_api::{
|
||||
AcquireSync, AsyncShmGfxTexture, AsyncShmGfxTextureCallback, CopyTexture, FillRect,
|
||||
FramebufferRect, GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage,
|
||||
GfxTexture, GfxWriteModifier, PendingShmUpload, ReleaseSync, ResetStatus,
|
||||
ShmGfxTexture, ShmMemory, SyncFile,
|
||||
GfxStagingBuffer, GfxTexture, GfxWriteModifier, PendingShmUpload, ReleaseSync,
|
||||
ResetStatus, ShmGfxTexture, ShmMemory, SyncFile,
|
||||
},
|
||||
rect::{Rect, Region},
|
||||
theme::Color,
|
||||
|
|
@ -335,6 +335,7 @@ impl ShmGfxTexture for TestGfxImage {
|
|||
impl AsyncShmGfxTexture for TestGfxImage {
|
||||
fn async_upload(
|
||||
self: Rc<Self>,
|
||||
_staging: &Rc<dyn GfxStagingBuffer>,
|
||||
_callback: Rc<dyn AsyncShmGfxTextureCallback>,
|
||||
mem: Rc<dyn ShmMemory>,
|
||||
_damage: Region,
|
||||
|
|
|
|||
20
src/text.rs
20
src/text.rs
|
|
@ -3,8 +3,8 @@ use {
|
|||
cpu_worker::{AsyncCpuWork, CpuJob, CpuWork, CpuWorker, PendingJob},
|
||||
format::ARGB8888,
|
||||
gfx_api::{
|
||||
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxContext, GfxError, GfxTexture,
|
||||
PendingShmUpload,
|
||||
AsyncShmGfxTexture, AsyncShmGfxTextureCallback, GfxContext, GfxError, GfxStagingBuffer,
|
||||
GfxTexture, PendingShmUpload, STAGING_UPLOAD,
|
||||
},
|
||||
pango::{
|
||||
consts::{
|
||||
|
|
@ -302,6 +302,7 @@ impl Drop for TextTexture {
|
|||
struct Shared {
|
||||
cpu_worker: Rc<CpuWorker>,
|
||||
ctx: Rc<dyn GfxContext>,
|
||||
staging: CloneCell<Option<Rc<dyn GfxStagingBuffer>>>,
|
||||
textures: DoubleBuffered<TextBuffer>,
|
||||
pending_render: Cell<Option<PendingJob>>,
|
||||
pending_upload: Cell<Option<PendingShmUpload>>,
|
||||
|
|
@ -367,6 +368,7 @@ impl TextTexture {
|
|||
let data = Rc::new(Shared {
|
||||
cpu_worker: cpu_worker.clone(),
|
||||
ctx: ctx.clone(),
|
||||
staging: Default::default(),
|
||||
textures: Default::default(),
|
||||
pending_render: Default::default(),
|
||||
pending_upload: Default::default(),
|
||||
|
|
@ -528,9 +530,22 @@ impl CpuJob for RenderJob {
|
|||
}
|
||||
}
|
||||
};
|
||||
let mut staging_opt = data.staging.take();
|
||||
if let Some(staging) = &staging_opt {
|
||||
if staging.size() != tex.staging_size() {
|
||||
staging_opt = None;
|
||||
}
|
||||
}
|
||||
let staging = match staging_opt {
|
||||
Some(s) => s,
|
||||
None => data
|
||||
.ctx
|
||||
.create_staging_buffer(tex.staging_size(), STAGING_UPLOAD),
|
||||
};
|
||||
let pending = tex
|
||||
.clone()
|
||||
.async_upload(
|
||||
&staging,
|
||||
data.clone(),
|
||||
Rc::new(rt.data),
|
||||
Region::new2(Rect::new_sized_unchecked(0, 0, rt.width, rt.height)),
|
||||
|
|
@ -538,6 +553,7 @@ impl CpuJob for RenderJob {
|
|||
.map_err(TextError::Upload);
|
||||
if pending.is_ok() {
|
||||
data.textures.back().tex.set(Some(tex));
|
||||
data.staging.set(Some(staging));
|
||||
}
|
||||
match pending {
|
||||
Ok(Some(p)) => data.pending_upload.set(Some(p)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue