mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 04:20:28 +00:00
DISPMANX: now waiting for free pages after issuing flip, instead of before, to avoid input lag.
This commit is contained in:
parent
5a1e8d55fb
commit
7ae7e2eaee
@ -54,6 +54,10 @@ struct dispmanx_surface
|
|||||||
struct dispmanx_page *pages;
|
struct dispmanx_page *pages;
|
||||||
/* the page that's currently on screen */
|
/* the page that's currently on screen */
|
||||||
struct dispmanx_page *current_page;
|
struct dispmanx_page *current_page;
|
||||||
|
/*The page to wich we will dump the render. We need to know this
|
||||||
|
* already when we enter the surface update function. No time to wait
|
||||||
|
* for free pages before blitting and showing the just rendered frame! */
|
||||||
|
struct dispmanx_page *next_page;
|
||||||
unsigned int bpp;
|
unsigned int bpp;
|
||||||
|
|
||||||
VC_RECT_T src_rect;
|
VC_RECT_T src_rect;
|
||||||
@ -173,7 +177,6 @@ static void dispmanx_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
|
|||||||
|
|
||||||
/* We mark as free the page that was visible until now */
|
/* We mark as free the page that was visible until now */
|
||||||
surface->current_page->used = false;
|
surface->current_page->used = false;
|
||||||
|
|
||||||
slock_unlock(surface->current_page->page_used_mutex);
|
slock_unlock(surface->current_page->page_used_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +263,11 @@ static void dispmanx_surface_setup(void *data, int src_width, int src_height,
|
|||||||
surface->pages[i].page_used_mutex = slock_new();
|
surface->pages[i].page_used_mutex = slock_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No need to mutex this access to the "used" member because
|
||||||
|
* the flipping/callbacks are not still running */
|
||||||
|
surface->next_page = &(surface->pages[0]);
|
||||||
|
surface->next_page->used = true;
|
||||||
|
|
||||||
/* The "visible" width obtained from the core pitch. We blit based on
|
/* The "visible" width obtained from the core pitch. We blit based on
|
||||||
* the "visible" width, for cores with things between scanlines. */
|
* the "visible" width, for cores with things between scanlines. */
|
||||||
int visible_width = visible_pitch / (bpp / 8);
|
int visible_width = visible_pitch / (bpp / 8);
|
||||||
@ -314,35 +322,42 @@ static void dispmanx_surface_update_async(void *data, const void *frame,
|
|||||||
static void dispmanx_surface_update(void *data, const void *frame,
|
static void dispmanx_surface_update(void *data, const void *frame,
|
||||||
struct dispmanx_surface *surface)
|
struct dispmanx_surface *surface)
|
||||||
{
|
{
|
||||||
|
/* Updating is very delicate: we REALLY want to show the just rendered frame ASAP,
|
||||||
|
* so we dump and issue flip, and then we can wait for free pages, but we don't
|
||||||
|
* want to wait for free pages at the beggining of the update or we will be
|
||||||
|
* adding lag! */
|
||||||
|
|
||||||
struct dispmanx_video *_dispvars = data;
|
struct dispmanx_video *_dispvars = data;
|
||||||
struct dispmanx_page *page = NULL;
|
|
||||||
|
|
||||||
settings_t *settings = config_get_ptr();
|
settings_t *settings = config_get_ptr();
|
||||||
|
|
||||||
/* Dispmanx doesn't support more than one pending pageflip.
|
/* Frame blitting */
|
||||||
* It causes lockups. */
|
vc_dispmanx_resource_write_data(surface->next_page->resource, surface->pixformat,
|
||||||
|
surface->pitch, (void*)frame, &(surface->bmp_rect));
|
||||||
|
|
||||||
|
/* Dispmanx doesn't support more than one pending pageflip. Doing so would overwrite
|
||||||
|
* the page in the callback function, so we would be always freeing the same page. */
|
||||||
slock_lock(_dispvars->pending_mutex);
|
slock_lock(_dispvars->pending_mutex);
|
||||||
if (_dispvars->pageflip_pending > 0)
|
if (_dispvars->pageflip_pending > 0)
|
||||||
scond_wait(_dispvars->vsync_condition, _dispvars->pending_mutex);
|
scond_wait(_dispvars->vsync_condition, _dispvars->pending_mutex);
|
||||||
slock_unlock(_dispvars->pending_mutex);
|
slock_unlock(_dispvars->pending_mutex);
|
||||||
|
|
||||||
page = dispmanx_get_free_page(_dispvars, surface);
|
|
||||||
|
|
||||||
/* Frame blitting */
|
|
||||||
vc_dispmanx_resource_write_data(page->resource, surface->pixformat,
|
|
||||||
surface->pitch, (void*)frame, &(surface->bmp_rect));
|
|
||||||
|
|
||||||
/* Issue a page flip that will be done at the next vsync. */
|
/* Issue a page flip that will be done at the next vsync. */
|
||||||
_dispvars->update = vc_dispmanx_update_start(0);
|
_dispvars->update = vc_dispmanx_update_start(0);
|
||||||
|
|
||||||
vc_dispmanx_element_change_source(_dispvars->update, surface->element,
|
vc_dispmanx_element_change_source(_dispvars->update, surface->element,
|
||||||
page->resource);
|
surface->next_page->resource);
|
||||||
|
|
||||||
vc_dispmanx_update_submit(_dispvars->update, dispmanx_vsync_callback, (void*)page);
|
vc_dispmanx_update_submit(_dispvars->update,
|
||||||
|
dispmanx_vsync_callback, (void*)(surface->next_page));
|
||||||
|
|
||||||
slock_lock(_dispvars->pending_mutex);
|
slock_lock(_dispvars->pending_mutex);
|
||||||
_dispvars->pageflip_pending++;
|
_dispvars->pageflip_pending++;
|
||||||
slock_unlock(_dispvars->pending_mutex);
|
slock_unlock(_dispvars->pending_mutex);
|
||||||
|
|
||||||
|
/* Get the next page ready for our next surface_update re-entry.
|
||||||
|
* It's OK to wait now that we've issued the flip to the last produced frame! */
|
||||||
|
surface->next_page = dispmanx_get_free_page(_dispvars, surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable/disable bilinear filtering. */
|
/* Enable/disable bilinear filtering. */
|
||||||
@ -374,7 +389,9 @@ static void dispmanx_blank_console (void *data)
|
|||||||
-1,
|
-1,
|
||||||
&_dispvars->back_surface);
|
&_dispvars->back_surface);
|
||||||
|
|
||||||
dispmanx_surface_update(_dispvars, image, _dispvars->back_surface);
|
/* Updating 1-page surface synchronously asks for truble, since the 1st CB will
|
||||||
|
* signal but not free because the only page is on screen, so get_free will wait forever. */
|
||||||
|
dispmanx_surface_update_async(_dispvars, image, _dispvars->back_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *dispmanx_gfx_init(const video_info_t *video,
|
static void *dispmanx_gfx_init(const video_info_t *video,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user