From fcde9eb405a1702afc23073f329f554b99afe2f7 Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Thu, 27 Jul 2023 10:46:58 +0800 Subject: [PATCH] Add OnBeforeUpdate() and OnAfterUpdate() operations for Shadow engine --- src/newgal/drm/drmvideo.c | 148 +++++++++++++++++++++++-------------- src/newgal/drm/drmvideo.h | 1 + src/newgal/shadow/shadow.c | 9 ++- src/newgal/sysvideo.h | 8 ++ 4 files changed, 109 insertions(+), 57 deletions(-) diff --git a/src/newgal/drm/drmvideo.c b/src/newgal/drm/drmvideo.c index a4f11265..493e7fd1 100644 --- a/src/newgal/drm/drmvideo.c +++ b/src/newgal/drm/drmvideo.c @@ -127,6 +127,8 @@ static void DRM_UpdateRects(_THIS, int numrects, GAL_Rect *rects); static BOOL DRM_WaitVBlank(_THIS); static BOOL DRM_SyncUpdate(_THIS); static BOOL DRM_SyncUpdateAsync(_THIS); +static void DRM_OnBeforeUpdate(_THIS); +static void DRM_OnAfterUpdate(_THIS); #if IS_SHAREDFB_SCHEMA_PROCS /* DRM engine methods for clients under sharedfb schema and MiniGUI-Processes */ @@ -2426,25 +2428,75 @@ static void update_real_screen_memcpy(_THIS) } } -static void drm_dmabuf_start(DrmSurfaceBuffer *real_buff) +static void DRM_OnBeforeUpdate(_THIS) { - struct dma_buf_sync sync; + DrmVideoData *vdata = this->hidden; + DrmSurfaceBuffer *real_buff; + real_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;; - sync.flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_START; - if (ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync)) { - _WRN_PRINTF("Failed ioctl(DMA_BUF_IOCTL_SYNC): %m\n"); + if (vdata->dirty_fb_ok == 0 && + real_buff->prime_fd >= 0 && real_buff->dma_buff) { + struct dma_buf_sync sync; + + sync.flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_START; + if (ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync)) { + _WRN_PRINTF("Failed ioctl(DMA_BUF_IOCTL_SYNC): %m\n"); + } } } -static void drm_dmabuf_end(DrmSurfaceBuffer *real_buff) +static void DRM_OnAfterUpdate(_THIS) { - struct dma_buf_sync sync; - sync.flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_END; - if (ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync)) { - _WRN_PRINTF("Failed ioctl(DMA_BUF_IOCTL_SYNC): %m\n"); + DrmVideoData *vdata = this->hidden; + DrmSurfaceBuffer *real_buff; + real_buff = (DrmSurfaceBuffer *)vdata->real_screen->hwdata;; + + if (vdata->dirty_fb_ok == 0 && + real_buff->prime_fd >= 0 && real_buff->dma_buff) { + struct dma_buf_sync sync; + sync.flags = DMA_BUF_SYNC_WRITE | DMA_BUF_SYNC_END; + if (ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync)) { + _WRN_PRINTF("Failed ioctl(DMA_BUF_IOCTL_SYNC): %m\n"); + } } } +#ifdef _MGSCHEMA_COMPOSITING +static void refresh_cursor(_THIS) +{ + if (this->hidden->cursor && !this->hidden->cursor_buff) { + RECT csr_rc, eff_rc; + csr_rc.left = boxleft (this); + csr_rc.top = boxtop (this); + csr_rc.right = csr_rc.left + CURSORWIDTH; + csr_rc.bottom = csr_rc.top + CURSORHEIGHT; + + if (IntersectRect (&eff_rc, &csr_rc, &bound)) { + GAL_Rect src_rect, dst_rect; + src_rect.x = eff_rc.left - csr_rc.left; + src_rect.y = eff_rc.top - csr_rc.top; + src_rect.w = RECTW (eff_rc); + src_rect.h = RECTH (eff_rc); + + dst_rect.x = eff_rc.left; + dst_rect.y = eff_rc.top; + dst_rect.w = src_rect.w; + dst_rect.h = src_rect.h; + GAL_SetupBlitting (this->hidden->cursor, + this->hidden->real_screen, 0); + GAL_BlitSurface (this->hidden->cursor, &src_rect, + this->hidden->real_screen, &dst_rect); + GAL_CleanupBlitting (this->hidden->cursor, + this->hidden->real_screen); + } + } +} +#else +static inline void refresh_cursor(_THIS) { + (void)this; +} +#endif /* _MGSCHEMA_COMPOSITING */ + static void update_real_screen_helper(_THIS) { DrmVideoData* vdata = this->hidden; @@ -2462,9 +2514,6 @@ static void update_real_screen_helper(_THIS) clock_gettime(CLOCK_REALTIME, &ts_start); #endif - if (real_buff->prime_fd >= 0 && real_buff->dma_buff) - drm_dmabuf_start(real_buff); - BOOL hw_ok = FALSE; if (shadow_buff && vdata->driver && vdata->driver_ops->copy_buff) { GAL_Rect rect = { @@ -2485,8 +2534,7 @@ static void update_real_screen_helper(_THIS) update_real_screen_memcpy(this); } - if (real_buff->prime_fd >= 0 && real_buff->dma_buff) - drm_dmabuf_end(real_buff); + refresh_cursor(this); #if 0 // def _DEBUG double elapsed = get_elapsed_seconds(&ts_start, NULL); @@ -2547,17 +2595,19 @@ static void* task_do_update(void *data) sem_wait(this->hidden->update_lock); if (RECTH(this->hidden->update_rect)) { + DRM_OnBeforeUpdate(this); update_real_screen_helper(this); - /* TODO: update cursor under compositing schema */ - drmModeClip clip = { - this->hidden->update_rect.left, - this->hidden->update_rect.top, - this->hidden->update_rect.right, - this->hidden->update_rect.bottom }; + DRM_OnAfterUpdate(this); - if (drmModeDirtyFB(this->hidden->dev_fd, - this->hidden->scanout_buff_id, &clip, 1)) { - _WRN_PRINTF("Failed drmModeDirtyFB: %m\n"); + if (this->hidden->dirty_fb_ok) { + drmModeClip clip = { + this->hidden->update_rect.left, + this->hidden->update_rect.top, + this->hidden->update_rect.right, + this->hidden->update_rect.bottom }; + + drmModeDirtyFB(this->hidden->dev_fd, + this->hidden->scanout_buff_id, &clip, 1); } SetRectEmpty(&this->hidden->update_rect); @@ -2789,6 +2839,16 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, #endif /* IS_COMPOSITING_SCHEMA */ GAL_FreeSurface (current); + + drmModeClip clip = { 0, 0, 1, 1 }; + if (drmModeDirtyFB(vdata->dev_fd, + vdata->scanout_buff_id, &clip, 1) == 0) { + vdata->dirty_fb_ok = 1; + } + else { + _WRN_PRINTF("Failed drmModeDirtyFB: %m\n"); + } + if (vdata->shadow_screen) { if (create_async_updater(this) == 0) { vdata->shadow_screen->flags |= GAL_ASYNCBLIT; @@ -2799,6 +2859,10 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, return vdata->shadow_screen; } + else if (vdata->dirty_fb_ok == 0) { + this->OnBeforeUpdate = DRM_OnBeforeUpdate; + this->OnAfterUpdate = DRM_OnAfterUpdate; + } return vdata->real_screen; @@ -3717,7 +3781,7 @@ static BOOL DRM_SyncUpdate(_THIS) #ifndef _MGSCHEMA_COMPOSITING if (this->hidden->dbl_buff && this->hidden->update_lock != SEM_FAILED) { - sem_wait (this->hidden->update_lock); + sem_wait(this->hidden->update_lock); } #endif @@ -3743,46 +3807,20 @@ static BOOL DRM_SyncUpdate(_THIS) bound = *dirty_rc; if (this->hidden->shadow_screen) { + DRM_OnBeforeUpdate(this); update_real_screen_helper(this); + DRM_OnAfterUpdate(this); } -#ifdef _MGSCHEMA_COMPOSITING - if (this->hidden->cursor && !this->hidden->cursor_buff) { - RECT csr_rc, eff_rc; - csr_rc.left = boxleft (this); - csr_rc.top = boxtop (this); - csr_rc.right = csr_rc.left + CURSORWIDTH; - csr_rc.bottom = csr_rc.top + CURSORHEIGHT; - - if (IntersectRect (&eff_rc, &csr_rc, &bound)) { - GAL_Rect src_rect, dst_rect; - src_rect.x = eff_rc.left - csr_rc.left; - src_rect.y = eff_rc.top - csr_rc.top; - src_rect.w = RECTW (eff_rc); - src_rect.h = RECTH (eff_rc); - - dst_rect.x = eff_rc.left; - dst_rect.y = eff_rc.top; - dst_rect.w = src_rect.w; - dst_rect.h = src_rect.h; - GAL_SetupBlitting (this->hidden->cursor, - this->hidden->real_screen, 0); - GAL_BlitSurface (this->hidden->cursor, &src_rect, - this->hidden->real_screen, &dst_rect); - GAL_CleanupBlitting (this->hidden->cursor, - this->hidden->real_screen); - } - } -#endif /* _MGSCHEMA_COMPOSITING */ + refresh_cursor(this); if (this->hidden->driver && this->hidden->driver_ops->flush_driver) { this->hidden->driver_ops->flush_driver(this->hidden->driver); } - { + if (this->hidden->dirty_fb_ok) { drmModeClip clip = { bound.left, bound.top, bound.right, bound.bottom }; - drmModeDirtyFB(this->hidden->dev_fd, this->hidden->scanout_buff_id, &clip, 1); } diff --git a/src/newgal/drm/drmvideo.h b/src/newgal/drm/drmvideo.h index d4cca39d..33c551e9 100644 --- a/src/newgal/drm/drmvideo.h +++ b/src/newgal/drm/drmvideo.h @@ -103,6 +103,7 @@ typedef struct GAL_PrivateVideoData { uint32_t cap_dumb:1; uint32_t cap_vblank_high_crtc:1; uint32_t dbl_buff:1; + uint32_t dirty_fb_ok:1; uint32_t scanout_buff_id; int crtc_idx; diff --git a/src/newgal/shadow/shadow.c b/src/newgal/shadow/shadow.c index 4909463f..1e9bd758 100644 --- a/src/newgal/shadow/shadow.c +++ b/src/newgal/shadow/shadow.c @@ -677,12 +677,12 @@ update_helper(_THIS, GAL_VideoDevice *real_device, RECT *update_rect) else if (this->hidden->realfb_info->flags & _ROT_DIR_HFLIP) { op = BLIT_COPY_FLIP_H; dirty_rect = *update_rect; - _get_dst_rect_hflip (&dirty_rect, this->hidden->realfb_info); + _get_dst_rect_hflip(&dirty_rect, this->hidden->realfb_info); } else if (this->hidden->realfb_info->flags & _ROT_DIR_VFLIP) { op = BLIT_COPY_FLIP_V; dirty_rect = *update_rect; - _get_dst_rect_vflip (&dirty_rect, this->hidden->realfb_info); + _get_dst_rect_vflip(&dirty_rect, this->hidden->realfb_info); } else { dirty_rect = *update_rect; @@ -694,6 +694,9 @@ update_helper(_THIS, GAL_VideoDevice *real_device, RECT *update_rect) dst_rc.w = RECTW(dirty_rect); dst_rc.h = RECTH(dirty_rect); + if (real_device->OnBeforeUpdate) + real_device->OnBeforeUpdate(real_device); + BOOL hw_ok = FALSE; if ((dst_rc.w * dst_rc.h) >= this->hidden->min_pixels_using_hwaccl) { if (real_device->CopyHWSurface) { @@ -718,6 +721,8 @@ update_helper(_THIS, GAL_VideoDevice *real_device, RECT *update_rect) real_device->UpdateRects(real_device, 1, &dst_rc); if (real_device->SyncUpdate) real_device->SyncUpdate(real_device); + if (real_device->OnAfterUpdate) + real_device->OnAfterUpdate(real_device); SetRectEmpty(update_rect); } diff --git a/src/newgal/sysvideo.h b/src/newgal/sysvideo.h index 4f1f30bf..ca47b0b4 100644 --- a/src/newgal/sysvideo.h +++ b/src/newgal/sysvideo.h @@ -131,9 +131,17 @@ struct GAL_VideoDevice { /* Wait vertical blank */ BOOL (*WaitVBlank)(_THIS); + /* Shadow engine will call this before updating the dirty content + if it is not NULL. */ + void (*OnBeforeUpdate)(_THIS); + /* Synchronize the dirty content */ BOOL (*SyncUpdate)(_THIS); + /* Shadow engine will call this after updating the dirty content + if it is not NULL. */ + void (*OnAfterUpdate)(_THIS); + /* Reverse the effects VideoInit() -- called if VideoInit() fails or if the application is shutting down the video subsystem. */