mirror of
https://github.com/libretro/RetroArch
synced 2025-04-01 13:20:43 +00:00
Merge branch 'master' of https://github.com/libretro/RetroArch
This commit is contained in:
commit
21c835bd40
@ -50,7 +50,6 @@ struct dispmanx_video
|
||||
DISPMANX_DISPLAY_HANDLE_T display;
|
||||
DISPMANX_MODEINFO_T amode;
|
||||
DISPMANX_UPDATE_HANDLE_T update;
|
||||
DISPMANX_RESOURCE_HANDLE_T resources[NUMPAGES];
|
||||
DISPMANX_ELEMENT_HANDLE_T element;
|
||||
VC_IMAGE_TYPE_T pixFormat;
|
||||
VC_DISPMANX_ALPHA_T *alpha;
|
||||
@ -74,7 +73,8 @@ struct dispmanx_video
|
||||
|
||||
struct dispmanx_page *pages;
|
||||
struct dispmanx_page *currentPage;
|
||||
unsigned int pageflip_pending;
|
||||
struct dispmanx_page *nextPage;
|
||||
bool pageflip_pending;
|
||||
|
||||
/* For console blanking */
|
||||
int fd;
|
||||
@ -86,13 +86,10 @@ struct dispmanx_video
|
||||
scond_t *vsync_condition;
|
||||
slock_t *pending_mutex;
|
||||
|
||||
/* Mutex to isolate the vsync condition signaling */
|
||||
slock_t *vsync_cond_mutex;
|
||||
|
||||
/* Menu */
|
||||
bool menu_active;
|
||||
DISPMANX_ELEMENT_HANDLE_T menu_element;
|
||||
DISPMANX_RESOURCE_HANDLE_T menu_resources[2];
|
||||
DISPMANX_RESOURCE_HANDLE_T menu_resource;
|
||||
VC_IMAGE_TYPE_T menu_pixFormat;
|
||||
VC_DISPMANX_ALPHA_T *menu_alpha;
|
||||
VC_RECT_T menu_srcRect;
|
||||
@ -109,16 +106,7 @@ struct dispmanx_video
|
||||
|
||||
struct dispmanx_page
|
||||
{
|
||||
unsigned int numpage;
|
||||
struct dispmanx_page *next;
|
||||
/* This field will allow us to
|
||||
* access the main _dispvars struct
|
||||
* from the vsync CB function */
|
||||
struct dispmanx_video *dispvars;
|
||||
/* Each page has it's own mutex for
|
||||
* isolating it's used flag access. */
|
||||
slock_t *page_used_mutex;
|
||||
bool used;
|
||||
DISPMANX_RESOURCE_HANDLE_T resource;
|
||||
};
|
||||
|
||||
static void dispmanx_blank_console(void *data)
|
||||
@ -182,104 +170,25 @@ static void dispmanx_unblank_console(void *data)
|
||||
system("setterm -cursor on");
|
||||
}
|
||||
|
||||
/* Find a free page, clear it if necessary, and return the page.
|
||||
*
|
||||
* If no free page is available when called, wait for a page flip.
|
||||
*/
|
||||
static struct dispmanx_page *dispmanx_get_free_page(void* data)
|
||||
{
|
||||
unsigned i;
|
||||
struct dispmanx_video *_dispvars = data;
|
||||
struct dispmanx_page *page = NULL;
|
||||
|
||||
while (!page)
|
||||
{
|
||||
/* Try to find a free page */
|
||||
for (i = 0; i < NUMPAGES; ++i)
|
||||
{
|
||||
if (!_dispvars->pages[i].used)
|
||||
{
|
||||
page = (_dispvars->pages) + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no page is free at the moment,
|
||||
* wait until a free page is freed by vsync CB. */
|
||||
if (!page)
|
||||
{
|
||||
slock_lock(_dispvars->vsync_cond_mutex);
|
||||
scond_wait(_dispvars->vsync_condition, _dispvars->vsync_cond_mutex);
|
||||
slock_unlock(_dispvars->vsync_cond_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
slock_lock(page->page_used_mutex);
|
||||
page->used = true;
|
||||
slock_unlock(page->page_used_mutex);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static void vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
|
||||
{
|
||||
struct dispmanx_page *page = data;
|
||||
|
||||
if (!page)
|
||||
return;
|
||||
|
||||
/* We signal the vsync condition, just in case
|
||||
* we're waiting for it somewhere (no free pages, etc). */
|
||||
slock_lock(page->dispvars->vsync_cond_mutex);
|
||||
scond_signal(page->dispvars->vsync_condition);
|
||||
slock_unlock(page->dispvars->vsync_cond_mutex);
|
||||
|
||||
slock_lock(page->dispvars->pending_mutex);
|
||||
page->dispvars->pageflip_pending--;
|
||||
slock_unlock(page->dispvars->pending_mutex);
|
||||
|
||||
if (page->dispvars->currentPage)
|
||||
{
|
||||
slock_lock(page->dispvars->currentPage->page_used_mutex);
|
||||
|
||||
/* We mark as free the page that was visible until now */
|
||||
page->dispvars->currentPage->used = false;
|
||||
|
||||
slock_unlock(page->dispvars->currentPage->page_used_mutex);
|
||||
}
|
||||
|
||||
/* The page on which we just issued the flip that
|
||||
* caused this callback becomes the visible one */
|
||||
page->dispvars->currentPage = page;
|
||||
}
|
||||
|
||||
static void dispmanx_flip(struct dispmanx_page *page, void *data)
|
||||
{
|
||||
struct dispmanx_video *_dispvars = data;
|
||||
|
||||
if (!_dispvars)
|
||||
return;
|
||||
/* Changing the page to write must be done before the signaling
|
||||
* so we have the right page in nextPage when update_main continues */
|
||||
|
||||
/* Dispmanx doesn't support issuing more than one pageflip.
|
||||
* If we do, the second CB isn't called. */
|
||||
if (_dispvars->pageflip_pending > 0)
|
||||
{
|
||||
slock_lock(_dispvars->vsync_cond_mutex);
|
||||
scond_wait(_dispvars->vsync_condition, _dispvars->vsync_cond_mutex);
|
||||
slock_unlock(_dispvars->vsync_cond_mutex);
|
||||
}
|
||||
|
||||
/* Issue a page flip at the next vblank interval
|
||||
* (will be done at vsync anyway). */
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
vc_dispmanx_element_change_source(_dispvars->update, _dispvars->element,
|
||||
_dispvars->resources[page->numpage]);
|
||||
|
||||
vc_dispmanx_update_submit(_dispvars->update, vsync_callback, (void*)page);
|
||||
if (_dispvars->nextPage == &_dispvars->pages[0])
|
||||
_dispvars->nextPage = &_dispvars->pages[1];
|
||||
else
|
||||
_dispvars->nextPage = &_dispvars->pages[0];
|
||||
|
||||
/* These two things must be isolated "atomically" to avoid getting
|
||||
* a false positive in the pending_mutex test in update_main. */
|
||||
slock_lock(_dispvars->pending_mutex);
|
||||
_dispvars->pageflip_pending++;
|
||||
|
||||
_dispvars->pageflip_pending = false;
|
||||
scond_signal(_dispvars->vsync_condition);
|
||||
|
||||
slock_unlock(_dispvars->pending_mutex);
|
||||
}
|
||||
|
||||
@ -294,7 +203,7 @@ static void dispmanx_free_main_resources(void *data)
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
for (i = 0; i < NUMPAGES; i++)
|
||||
vc_dispmanx_resource_delete(_dispvars->resources[i]);
|
||||
vc_dispmanx_resource_delete(_dispvars->pages[i].resource);
|
||||
|
||||
vc_dispmanx_element_remove(_dispvars->update, _dispvars->element);
|
||||
vc_dispmanx_update_submit_sync(_dispvars->update);
|
||||
@ -387,14 +296,14 @@ static bool dispmanx_setup_scale(void *data, unsigned width,
|
||||
|
||||
/* We create as many resources as pages */
|
||||
for (i = 0; i < NUMPAGES; i++)
|
||||
_dispvars->resources[i] = vc_dispmanx_resource_create(_dispvars->pixFormat,
|
||||
_dispvars->pages[i].resource = vc_dispmanx_resource_create(_dispvars->pixFormat,
|
||||
_dispvars->visible_width, _dispvars->height, &(_dispvars->vcImagePtr));
|
||||
|
||||
/* Add element. */
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
_dispvars->element = vc_dispmanx_element_add(_dispvars->update, _dispvars->display, 0,
|
||||
&(_dispvars->dstRect), _dispvars->resources[0], &(_dispvars->srcRect),
|
||||
&(_dispvars->dstRect), _dispvars->pages[0].resource, &(_dispvars->srcRect),
|
||||
DISPMANX_PROTECTION_NONE, _dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0);
|
||||
|
||||
vc_dispmanx_update_submit_sync(_dispvars->update);
|
||||
@ -404,24 +313,33 @@ static bool dispmanx_setup_scale(void *data, unsigned width,
|
||||
|
||||
static void dispmanx_update_main(void *data, const void *frame)
|
||||
{
|
||||
struct dispmanx_page *page = NULL;
|
||||
struct dispmanx_video *_dispvars = data;
|
||||
|
||||
if (!_dispvars)
|
||||
return;
|
||||
|
||||
page = dispmanx_get_free_page(_dispvars);
|
||||
|
||||
if (!page)
|
||||
return;
|
||||
/* Wait until last issued flip completes to get the free page
|
||||
* that the vsync cb will put in nextPage. Also, dispmanx doesn't
|
||||
* support issuing more than one pageflip.*/
|
||||
slock_lock(_dispvars->pending_mutex);
|
||||
if (_dispvars->pageflip_pending)
|
||||
{
|
||||
scond_wait(_dispvars->vsync_condition, _dispvars->pending_mutex);
|
||||
}
|
||||
slock_unlock(_dispvars->pending_mutex);
|
||||
|
||||
/* Frame blitting */
|
||||
vc_dispmanx_resource_write_data(_dispvars->resources[page->numpage], _dispvars->pixFormat,
|
||||
vc_dispmanx_resource_write_data(_dispvars->nextPage->resource, _dispvars->pixFormat,
|
||||
_dispvars->pitch, (void *)frame, &(_dispvars->bmpRect));
|
||||
|
||||
/* Issue flipping: we send the page
|
||||
* to the dispmanx API internal flipping FIFO stack. */
|
||||
dispmanx_flip (page, _dispvars);
|
||||
/* Issue a page flip that will be done at the next vsync. */
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
vc_dispmanx_element_change_source(_dispvars->update, _dispvars->element,
|
||||
_dispvars->nextPage->resource);
|
||||
|
||||
vc_dispmanx_update_submit(_dispvars->update, vsync_callback, (void*)_dispvars);
|
||||
|
||||
slock_lock(_dispvars->pending_mutex);
|
||||
_dispvars->pageflip_pending = true;
|
||||
slock_unlock(_dispvars->pending_mutex);
|
||||
}
|
||||
|
||||
static void *dispmanx_gfx_init(const video_info_t *video,
|
||||
@ -436,9 +354,11 @@ static void *dispmanx_gfx_init(const video_info_t *video,
|
||||
_dispvars->bytes_per_pixel = video->rgb32 ? 4 : 2;
|
||||
_dispvars->screen = 0;
|
||||
_dispvars->vcImagePtr = 0;
|
||||
_dispvars->pageflip_pending = 0;
|
||||
_dispvars->pageflip_pending = false;
|
||||
_dispvars->currentPage = NULL;
|
||||
_dispvars->pages = calloc(NUMPAGES, sizeof(struct dispmanx_page));
|
||||
_dispvars->menu_active = false;
|
||||
_dispvars->nextPage = &_dispvars->pages[0];
|
||||
|
||||
if (!_dispvars->pages)
|
||||
{
|
||||
@ -446,18 +366,9 @@ static void *dispmanx_gfx_init(const video_info_t *video,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < NUMPAGES; i++)
|
||||
{
|
||||
_dispvars->pages[i].numpage = i;
|
||||
_dispvars->pages[i].used = false;
|
||||
_dispvars->pages[i].dispvars = _dispvars;
|
||||
_dispvars->pages[i].page_used_mutex = slock_new();
|
||||
}
|
||||
|
||||
/* Initialize the rest of the mutexes and conditions. */
|
||||
_dispvars->vsync_condition = scond_new();
|
||||
_dispvars->pending_mutex = slock_new();
|
||||
_dispvars->vsync_cond_mutex = slock_new();
|
||||
|
||||
bcm_host_init();
|
||||
|
||||
@ -491,6 +402,7 @@ static bool dispmanx_gfx_frame(void *data, const void *frame, unsigned width,
|
||||
RARCH_ERR("video_dispmanx: frame resolution set failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
dispmanx_blank_console (_dispvars);
|
||||
}
|
||||
|
||||
@ -498,13 +410,6 @@ static bool dispmanx_gfx_frame(void *data, const void *frame, unsigned width,
|
||||
{
|
||||
char buf[128];
|
||||
video_monitor_get_fps(buf, sizeof(buf), NULL, 0);
|
||||
|
||||
/* Synchronous flipping of the menu buffers. */
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
vc_dispmanx_element_change_source(_dispvars->update, _dispvars->menu_element,
|
||||
_dispvars->menu_resources[_dispvars->menu_flip_page]);
|
||||
vc_dispmanx_update_submit_sync(_dispvars->update);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Update main game screen: locate free page, blit and flip. */
|
||||
@ -522,9 +427,7 @@ static void dispmanx_free_menu_resources (void *data)
|
||||
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
vc_dispmanx_resource_delete(_dispvars->menu_resources[0]);
|
||||
vc_dispmanx_resource_delete(_dispvars->menu_resources[1]);
|
||||
|
||||
vc_dispmanx_resource_delete(_dispvars->menu_resource);
|
||||
vc_dispmanx_element_remove(_dispvars->update, _dispvars->menu_element);
|
||||
|
||||
vc_dispmanx_update_submit_sync(_dispvars->update);
|
||||
@ -570,7 +473,7 @@ static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32
|
||||
_dispvars->menu_pixFormat = VC_IMAGE_RGBA16;
|
||||
_dispvars->menu_flip_page = 0;
|
||||
|
||||
/* Transparency disabled */
|
||||
/* Menu transparency has a fixed value for now. */
|
||||
layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
|
||||
#if 0
|
||||
layerAlpha.opacity = (unsigned char)(255.0f * alpha);
|
||||
@ -596,33 +499,26 @@ static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32
|
||||
vc_dispmanx_rect_set(&(_dispvars->menu_bmpRect), 0, 0, _dispvars->menu_width, _dispvars->menu_height);
|
||||
vc_dispmanx_rect_set(&(_dispvars->menu_srcRect), 0, 0, _dispvars->menu_width << 16, _dispvars->menu_height << 16);
|
||||
|
||||
/* We create two resources for the menu element. */
|
||||
_dispvars->menu_resources[0] = vc_dispmanx_resource_create(_dispvars->menu_pixFormat,
|
||||
_dispvars->menu_width, _dispvars->menu_height, &(_dispvars->vcImagePtr));
|
||||
_dispvars->menu_resources[1] = vc_dispmanx_resource_create(_dispvars->menu_pixFormat,
|
||||
/* Create resource for the menu element. */
|
||||
_dispvars->menu_resource = vc_dispmanx_resource_create(_dispvars->menu_pixFormat,
|
||||
_dispvars->menu_width, _dispvars->menu_height, &(_dispvars->vcImagePtr));
|
||||
|
||||
/* Add the menu element. */
|
||||
_dispvars->update = vc_dispmanx_update_start(0);
|
||||
|
||||
_dispvars->menu_element = vc_dispmanx_element_add(_dispvars->update, _dispvars->display, 0,
|
||||
&(_dispvars->menu_dstRect), _dispvars->menu_resources[0], &(_dispvars->menu_srcRect),
|
||||
&(_dispvars->menu_dstRect), _dispvars->menu_resource, &(_dispvars->menu_srcRect),
|
||||
DISPMANX_PROTECTION_NONE, _dispvars->menu_alpha, 0, (DISPMANX_TRANSFORM_T)0);
|
||||
|
||||
vc_dispmanx_update_submit_sync(_dispvars->update);
|
||||
}
|
||||
|
||||
/* Flipping is done in every frame,
|
||||
* in the gfx_frame function.
|
||||
* That's why why change flip page here instead. */
|
||||
_dispvars->menu_flip_page = !_dispvars->menu_flip_page;
|
||||
|
||||
/* Frame blitting. */
|
||||
vc_dispmanx_resource_write_data(_dispvars->menu_resources[_dispvars->menu_flip_page],
|
||||
vc_dispmanx_resource_write_data(_dispvars->menu_resource,
|
||||
_dispvars->menu_pixFormat, _dispvars->menu_pitch, (void *)frame, &(_dispvars->menu_bmpRect));
|
||||
|
||||
/* We don't flip the menu buffers here:
|
||||
* that's done in the gfx_frame function when menu is active. */
|
||||
/* We don't need to flip buffers: one is enough for menu. We sync in gfx_frame, on the
|
||||
* dispmanx_update_main() call, that is called with menu active, too. */
|
||||
}
|
||||
|
||||
static void dispmanx_gfx_set_nonblock_state(void *data, bool state)
|
||||
@ -744,9 +640,6 @@ static void dispmanx_gfx_free(void *data)
|
||||
slock_free(_dispvars->pending_mutex);
|
||||
scond_free(_dispvars->vsync_condition);
|
||||
|
||||
for (i = 0; i < NUMPAGES; i++)
|
||||
slock_free(_dispvars->pages[i].page_used_mutex);
|
||||
|
||||
if (_dispvars->pages)
|
||||
free (_dispvars->pages);
|
||||
_dispvars->pages = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user