use drmWaitVBlank

This commit is contained in:
Vincent Wei
2023-07-12 21:35:32 +08:00
parent 51b09bc2ed
commit cfd3311f86
2 changed files with 205 additions and 33 deletions

View File

@@ -1694,6 +1694,8 @@ static int DRM_SetColors(_THIS, int firstcolor, int ncolors, GAL_Color *colors)
return(1);
}
static void cancel_async_updater(_THIS);
static void DRM_VideoQuit(_THIS)
{
if (this->screen->pixels != NULL) {
@@ -1703,6 +1705,8 @@ static void DRM_VideoQuit(_THIS)
#if IS_SHAREDFB_SCHEMA_PROCS
if (mgIsServer)
#endif
cancel_async_updater(this);
#ifndef _MGSCHEMA_COMPOSITING
if (this->hidden->dbl_buff && this->hidden->update_lock != SEM_FAILED) {
if (sem_unlink (SEM_UPDATE_LOCK)) {
@@ -2403,6 +2407,147 @@ static int drm_allocate_dma_buffers(DrmVideoData* vdata, int size)
}
#endif
static void drm_dmabuf_start(DrmSurfaceBuffer *real_buff)
{
struct dma_buf_sync sync;
if (real_buff->prime_fd < 0)
return;
sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_START;
ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync);
}
static void drm_dmabuf_end(DrmSurfaceBuffer *real_buff)
{
struct dma_buf_sync sync;
if (real_buff->prime_fd < 0)
return;
sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END;
ioctl(real_buff->prime_fd, DMA_BUF_IOCTL_SYNC, &sync);
}
static void update_real_screen_memcpy(_THIS)
{
DrmSurfaceBuffer *real_buff, *shadow_buff;
real_buff = (DrmSurfaceBuffer *)this->hidden->real_screen->hwdata;
shadow_buff = (DrmSurfaceBuffer *)this->hidden->shadow_screen->hwdata;
uint32_t i;
uint8_t *src, *dst;
RECT *update_rect = &this->hidden->update_rect;
size_t count = shadow_buff->cpp * RECTWP(update_rect);
src = shadow_buff->buff;
src += shadow_buff->pitch * update_rect->top +
shadow_buff->cpp * update_rect->left;
src += shadow_buff->offset;
dst = real_buff->buff;
dst += real_buff->pitch * update_rect->top +
real_buff->cpp * update_rect->left;
dst += real_buff->offset;
drm_dmabuf_start(real_buff);
for (i = 0; i < RECTHP(update_rect); i++) {
memcpy(dst, src, count);
src += shadow_buff->pitch;
dst += shadow_buff->pitch;
}
drm_dmabuf_end(real_buff);
}
static void* task_do_update(void *data)
{
_THIS = data;
int fd = dup(this->hidden->dev_fd);
if (fd < 0)
return NULL;
if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) {
goto error;
}
drmVBlank vbl;
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 0;
vbl.request.signal = 0;
if (drmWaitVBlank(fd, &vbl)) {
_ERR_PRINTF("Failed drmWaitVBlank(): %m\n");
goto error;
}
this->hidden->updater_ready = 1;
sem_post(&this->hidden->sync_sem);
do {
vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_NEXTONMISS;
vbl.request.sequence = 1;
vbl.request.signal = 0;
drmWaitVBlank(fd, &vbl);
_DBG_PRINTF("It's time to update real screen. (%ld.%06ld)\n",
vbl.reply.tval_sec, vbl.reply.tval_usec);
pthread_mutex_lock(&this->hidden->update_mutex);
if (RECTH(this->hidden->update_rect)) {
update_real_screen_memcpy(this);
SetRectEmpty(&this->hidden->update_rect);
}
pthread_mutex_unlock(&this->hidden->update_mutex);
pthread_testcancel();
} while (1);
close(fd);
return NULL;
error:
if (fd >= 0)
close(fd);
sem_post(&this->hidden->sync_sem);
return NULL;
}
static int create_async_updater(_THIS)
{
if (sem_init(&this->hidden->sync_sem, 0, 0))
return -1;
if (pthread_mutex_init(&this->hidden->update_mutex, NULL))
return -1;
pthread_attr_t attr;
pthread_attr_init(&attr);
struct sched_param sp = { 90 };
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
pthread_attr_setschedparam(&attr, &sp);
if (pthread_create(&this->hidden->update_thd, &attr,
task_do_update, this))
return -1;
sem_wait(&this->hidden->sync_sem);
pthread_attr_destroy(&attr);
return this->hidden->updater_ready ? 0 : -1;
}
static void cancel_async_updater(_THIS)
{
if (this->hidden->updater_ready) {
pthread_cancel(this->hidden->update_thd);
pthread_join(this->hidden->update_thd, NULL);
pthread_mutex_destroy(&this->hidden->update_mutex);
sem_destroy(&this->hidden->sync_sem);
}
}
/* DRM engine methods for dumb buffers */
static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current,
int width, int height, int bpp, Uint32 flags)
@@ -2558,8 +2703,12 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current,
#endif /* IS_COMPOSITING_SCHEMA */
GAL_FreeSurface (current);
if (vdata->shadow_screen)
if (vdata->shadow_screen) {
if (create_async_updater(this)) {
}
return vdata->shadow_screen;
}
return vdata->real_screen;
@@ -3437,32 +3586,6 @@ static void DRM_UpdateRects (_THIS, int numrects, GAL_Rect *rects)
#endif
}
static void drm_dmabuf_start(_THIS)
{
struct dma_buf_sync sync;
DrmSurfaceBuffer *real_buffer;
real_buffer = (DrmSurfaceBuffer *)this->hidden->real_screen->hwdata;
if (real_buffer->prime_fd < 0)
return;
sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_START;
ioctl(real_buffer->prime_fd, DMA_BUF_IOCTL_SYNC, &sync);
}
static void drm_dmabuf_end(_THIS)
{
struct dma_buf_sync sync;
DrmSurfaceBuffer *real_buffer;
real_buffer = (DrmSurfaceBuffer *)this->hidden->real_screen->hwdata;
if (real_buffer->prime_fd < 0)
return;
sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END;
ioctl(real_buffer->prime_fd, DMA_BUF_IOCTL_SYNC, &sync);
}
static BOOL DRM_SyncUpdate(_THIS)
{
BOOL retval = FALSE;
@@ -3514,13 +3637,13 @@ static BOOL DRM_SyncUpdate(_THIS)
dst += real_buff->pitch * bound.top + real_buff->cpp * bound.left;
dst += real_buff->offset;
drm_dmabuf_start(this);
drm_dmabuf_start(real_buff);
for (i = 0; i < RECTH (bound); i++) {
memcpy (dst, src, count);
src += shadow_buff->pitch;
dst += shadow_buff->pitch;
}
drm_dmabuf_end(this);
drm_dmabuf_end(real_buff);
}
else {
GAL_Rect src_rect, dst_rect;
@@ -3592,6 +3715,53 @@ ret:
return retval;
}
static BOOL DRM_SyncUpdateAsync(_THIS)
{
BOOL retval = FALSE;
RECT* dirty_rc;
RECT bound;
#ifndef _MGSCHEMA_COMPOSITING
if (this->hidden->dbl_buff && this->hidden->update_lock != SEM_FAILED) {
sem_wait (this->hidden->update_lock);
}
#endif
#if IS_SHAREDFB_SCHEMA_PROCS
GAL_ShadowSurfaceHeader* hdr;
if (this->hidden->shadow_screen->flags & GAL_HWSURFACE) {
hdr = (GAL_ShadowSurfaceHeader*)
((DrmSurfaceBuffer*)this->hidden->shadow_screen->hwdata)->buff;
}
else {
hdr = (GAL_ShadowSurfaceHeader*)
((uint8_t*)this->hidden->shadow_screen->pixels -
this->hidden->shadow_screen->pixels_off);
}
dirty_rc = &hdr->dirty_rc;
#else
dirty_rc = &this->hidden->dirty_rc;
#endif
if (IsRectEmpty(dirty_rc))
goto ret;
bound = *dirty_rc;
pthread_mutex_lock(&this->hidden->update_mutex);
RECT *update_rect = &this->hidden->update_rect;
GetBoundRect(update_rect, &bound, update_rect);
pthread_mutex_unlock(&this->hidden->update_mutex);
retval = TRUE;
ret:
#ifndef _MGSCHEMA_COMPOSITING
if (this->hidden->dbl_buff && this->hidden->update_lock != SEM_FAILED) {
sem_post (this->hidden->update_lock);
}
#endif
return retval;
}
#if 0
static BOOL DRM_SyncUpdateDMA (_THIS)
{

View File

@@ -119,10 +119,12 @@ typedef struct GAL_PrivateVideoData {
DrmModeInfo* saved_info;
drmModeCrtc* saved_crtc;
#if 0 /* deprecated code */
uint32_t console_buff_id;
uint8_t* scanout_fb;
#endif /* deprecated code */
/* async updater */
int updater_ready;
RECT update_rect;
pthread_t update_thd;
pthread_mutex_t update_mutex;
sem_t sync_sem;
} DrmVideoData;
#endif /* _NEWGAL_DRIVIDEO_H */