(dispmanx_gfx.c) Cleanups

This commit is contained in:
twinaphex 2015-11-28 17:00:44 +01:00
parent c23846c5dc
commit 70850c8ca3

View File

@ -122,7 +122,8 @@ struct dispmanx_video
}; };
/* If no free page is available when called, wait for a page flip. */ /* If no free page is available when called, wait for a page flip. */
static struct dispmanx_page *dispmanx_get_free_page(void *data, struct dispmanx_surface *surface) { static struct dispmanx_page *dispmanx_get_free_page(void *data, struct dispmanx_surface *surface)
{
unsigned i; unsigned i;
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
struct dispmanx_page *page = NULL; struct dispmanx_page *page = NULL;
@ -130,7 +131,8 @@ static struct dispmanx_page *dispmanx_get_free_page(void *data, struct dispmanx_
while (!page) while (!page)
{ {
/* Try to find a free page */ /* Try to find a free page */
for (i = 0; i < surface->numpages; ++i) { for (i = 0; i < surface->numpages; ++i)
{
if (!surface->pages[i].used) if (!surface->pages[i].used)
{ {
page = (surface->pages) + i; page = (surface->pages) + i;
@ -140,10 +142,11 @@ static struct dispmanx_page *dispmanx_get_free_page(void *data, struct dispmanx_
/* If no page is free at the moment, /* If no page is free at the moment,
* wait until a free page is freed by vsync CB. */ * wait until a free page is freed by vsync CB. */
if (!page) { if (!page)
slock_lock(_dispvars->vsync_cond_mutex); {
scond_wait(_dispvars->vsync_condition, _dispvars->vsync_cond_mutex); slock_lock(_dispvars->vsync_cond_mutex);
slock_unlock(_dispvars->vsync_cond_mutex); scond_wait(_dispvars->vsync_condition, _dispvars->vsync_cond_mutex);
slock_unlock(_dispvars->vsync_cond_mutex);
} }
} }
@ -163,7 +166,8 @@ static void dispmanx_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
/* Marking the page as free must be done before the signaling /* Marking the page as free must be done before the signaling
* so when update_main continues (it won't continue until we signal) * so when update_main continues (it won't continue until we signal)
* we can chose this page as free */ * we can chose this page as free */
if (surface->current_page) { if (surface->current_page)
{
slock_lock(surface->current_page->page_used_mutex); slock_lock(surface->current_page->page_used_mutex);
/* We mark as free the page that was visible until now */ /* We mark as free the page that was visible until now */
@ -197,12 +201,12 @@ static void dispmanx_surface_free(void *data, struct dispmanx_surface **sp)
* So we wait for any pending flips to complete before freeing any surface. */ * So we wait for any pending flips to complete before freeing any surface. */
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);
for (i = 0; i < surface->numpages; i++) { for (i = 0; i < surface->numpages; i++)
{
vc_dispmanx_resource_delete(surface->pages[i].resource); vc_dispmanx_resource_delete(surface->pages[i].resource);
surface->pages[i].used = false; surface->pages[i].used = false;
slock_free(surface->pages[i].page_used_mutex); slock_free(surface->pages[i].page_used_mutex);
@ -218,22 +222,18 @@ static void dispmanx_surface_free(void *data, struct dispmanx_surface **sp)
*sp = NULL; *sp = NULL;
} }
static void dispmanx_surface_setup(void *data, static void dispmanx_surface_setup(void *data, int src_width, int src_height,
int src_width, int visible_pitch, int bpp, VC_IMAGE_TYPE_T pixformat,
int src_height, int alpha, float aspect, int numpages, int layer,
int visible_pitch, struct dispmanx_surface **sp)
int bpp,
VC_IMAGE_TYPE_T pixformat,
int alpha,
float aspect,
int numpages,
int layer,
struct dispmanx_surface **sp)
{ {
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
int i, dst_width, dst_height, dst_xpos, dst_ypos; int i, dst_width, dst_height, dst_xpos, dst_ypos;
struct dispmanx_surface *surface = NULL;
*sp = calloc (1, sizeof(struct dispmanx_surface)); *sp = calloc (1, sizeof(struct dispmanx_surface));
struct dispmanx_surface *surface = *sp;
surface = *sp;
/* Setup surface parameters */ /* Setup surface parameters */
surface->numpages = numpages; surface->numpages = numpages;
@ -264,7 +264,7 @@ static void dispmanx_surface_setup(void *data,
dst_height = _dispvars->dispmanx_height; dst_height = _dispvars->dispmanx_height;
/* If we obtain a scaled image width that is bigger than the physical screen width, /* If we obtain a scaled image width that is bigger than the physical screen width,
* then we keep the physical screen width as our maximun width. */ * then we keep the physical screen width as our maximun width. */
if (dst_width > _dispvars->dispmanx_width) if (dst_width > _dispvars->dispmanx_width)
dst_width = _dispvars->dispmanx_width; dst_width = _dispvars->dispmanx_width;
@ -276,41 +276,41 @@ static void dispmanx_surface_setup(void *data,
vc_dispmanx_rect_set(&surface->bmp_rect, 0, 0, src_width, src_height); vc_dispmanx_rect_set(&surface->bmp_rect, 0, 0, src_width, src_height);
vc_dispmanx_rect_set(&surface->src_rect, 0, 0, src_width << 16, src_height << 16); vc_dispmanx_rect_set(&surface->src_rect, 0, 0, src_width << 16, src_height << 16);
for (i = 0; i < surface->numpages; i++) { for (i = 0; i < surface->numpages; i++)
{
surface->pages[i].resource = vc_dispmanx_resource_create(pixformat, surface->pages[i].resource = vc_dispmanx_resource_create(pixformat,
visible_width, src_height, &(_dispvars->vc_image_ptr)); visible_width, src_height, &(_dispvars->vc_image_ptr));
} }
/* Add element. */ /* Add element. */
_dispvars->update = vc_dispmanx_update_start(0); _dispvars->update = vc_dispmanx_update_start(0);
surface->element = vc_dispmanx_element_add( surface->element = vc_dispmanx_element_add(
_dispvars->update,_dispvars->display, layer, _dispvars->update,_dispvars->display, layer,
&surface->dst_rect, surface->pages[0].resource, &surface->dst_rect, surface->pages[0].resource,
&surface->src_rect, DISPMANX_PROTECTION_NONE, &surface->src_rect, DISPMANX_PROTECTION_NONE,
&surface->alpha, 0, (DISPMANX_TRANSFORM_T)0); &surface->alpha, 0, (DISPMANX_TRANSFORM_T)0);
vc_dispmanx_update_submit_sync(_dispvars->update); vc_dispmanx_update_submit_sync(_dispvars->update);
} }
static void dispmanx_surface_update(void *data, const void *frame, struct dispmanx_surface *surface) static void dispmanx_surface_update(void *data, const void *frame,
struct dispmanx_surface *surface)
{ {
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
struct dispmanx_page *page = NULL; struct dispmanx_page *page = NULL;
/* Wait until last issued flip completes to get a free page. Also, /* Wait until last issued flip completes to get a free page. Also,
dispmanx doesn't support issuing more than one pageflip.*/ dispmanx doesn't support issuing more than one pageflip.*/
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); page = dispmanx_get_free_page(_dispvars, surface);
/* Frame blitting */ /* Frame blitting */
vc_dispmanx_resource_write_data(page->resource, surface->pixformat, vc_dispmanx_resource_write_data(page->resource, surface->pixformat,
surface->pitch, (void*)frame, &(surface->bmp_rect)); 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);
@ -335,16 +335,16 @@ static void dispmanx_blank_console (void *data)
float aspect = (float)_dispvars->dispmanx_width / (float)_dispvars->dispmanx_height; float aspect = (float)_dispvars->dispmanx_width / (float)_dispvars->dispmanx_height;
dispmanx_surface_setup(_dispvars, dispmanx_surface_setup(_dispvars,
2, 2,
2, 2,
4, 4,
16, 16,
VC_IMAGE_RGB565, VC_IMAGE_RGB565,
255, 255,
aspect, aspect,
1, 1,
-1, -1,
&_dispvars->back_surface); &_dispvars->back_surface);
dispmanx_surface_update(_dispvars, image, _dispvars->back_surface); dispmanx_surface_update(_dispvars, image, _dispvars->back_surface);
} }
@ -354,18 +354,24 @@ static void *dispmanx_gfx_init(const video_info_t *video,
{ {
struct dispmanx_video *_dispvars = calloc(1, sizeof(struct dispmanx_video)); struct dispmanx_video *_dispvars = calloc(1, sizeof(struct dispmanx_video));
if (!_dispvars)
return NULL;
bcm_host_init(); bcm_host_init();
_dispvars->display = vc_dispmanx_display_open(0 /* LCD */); _dispvars->display = vc_dispmanx_display_open(0 /* LCD */);
/* If the console framebuffer has active overscan settings, /* If the console framebuffer has active overscan settings,
* the user must have overscan_scale=1 in config.txt to have * the user must have overscan_scale=1 in config.txt to have
* the same size for both fb console and dispmanx. */ * the same size for both fb console and dispmanx. */
graphics_get_display_size(_dispvars->display, &_dispvars->dispmanx_width, &_dispvars->dispmanx_height); graphics_get_display_size(_dispvars->display,
&_dispvars->dispmanx_width, &_dispvars->dispmanx_height);
/* Setup surface parameters */ /* Setup surface parameters */
_dispvars->vc_image_ptr = 0; _dispvars->vc_image_ptr = 0;
_dispvars->pageflip_pending = 0; _dispvars->pageflip_pending = 0;
_dispvars->menu_active = false; _dispvars->menu_active = false;
_dispvars->rgb32 = video->rgb32; _dispvars->rgb32 = video->rgb32;
/* It's very important that we set aspect here because the /* It's very important that we set aspect here because the
* call seq when a core is loaded is gfx_init()->set_aspect()->gfx_frame() * call seq when a core is loaded is gfx_init()->set_aspect()->gfx_frame()
* and we don't want the main surface to be setup in set_aspect() * and we don't want the main surface to be setup in set_aspect()
@ -376,13 +382,13 @@ static void *dispmanx_gfx_init(const video_info_t *video,
_dispvars->vsync_condition = scond_new(); _dispvars->vsync_condition = scond_new();
_dispvars->vsync_cond_mutex = slock_new(); _dispvars->vsync_cond_mutex = slock_new();
_dispvars->pending_mutex = slock_new(); _dispvars->pending_mutex = slock_new();
_dispvars->core_width = 0; _dispvars->core_width = 0;
_dispvars->core_height = 0; _dispvars->core_height = 0;
_dispvars->menu_width = 0; _dispvars->menu_width = 0;
_dispvars->menu_height = 0; _dispvars->menu_height = 0;
_dispvars->main_surface = NULL; _dispvars->main_surface = NULL;
_dispvars->menu_surface = NULL; _dispvars->menu_surface = NULL;
if (input && input_data) if (input && input_data)
*input = NULL; *input = NULL;
@ -407,22 +413,21 @@ static bool dispmanx_gfx_frame(void *data, const void *frame, unsigned width,
_dispvars->core_height = height; _dispvars->core_height = height;
_dispvars->core_pitch = pitch; _dispvars->core_pitch = pitch;
if (_dispvars->main_surface != NULL) { if (_dispvars->main_surface != NULL)
dispmanx_surface_free(_dispvars, &_dispvars->main_surface); dispmanx_surface_free(_dispvars, &_dispvars->main_surface);
}
/* We need to recreate the main surface. */ /* We need to recreate the main surface. */
dispmanx_surface_setup(_dispvars, dispmanx_surface_setup(_dispvars,
width, width,
height, height,
pitch, pitch,
_dispvars->rgb32 ? 32 : 16, _dispvars->rgb32 ? 32 : 16,
_dispvars->rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565, _dispvars->rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565,
255, 255,
_dispvars->aspect, _dispvars->aspect,
3, 3,
0, 0,
&_dispvars->main_surface); &_dispvars->main_surface);
} }
if (_dispvars->menu_active) if (_dispvars->menu_active)
@ -441,40 +446,42 @@ static void dispmanx_set_texture_enable(void *data, bool state, bool full_screen
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
/* If it was active but it's not anymore... */ /* If it was active but it's not anymore... */
if (!state && _dispvars->menu_active) { if (!state && _dispvars->menu_active)
dispmanx_surface_free(_dispvars, &_dispvars->menu_surface); dispmanx_surface_free(_dispvars, &_dispvars->menu_surface);
}
_dispvars->menu_active = state; _dispvars->menu_active = state;
} }
static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32, static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32,
unsigned width, unsigned height, float alpha) unsigned width, unsigned height, float alpha)
{ {
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
if (_dispvars->menu_active) if (!_dispvars->menu_active)
{ return;
/* If menu is active in this frame but out menu surface is NULL, we allocate a new one.*/
if (_dispvars->menu_surface == NULL) {
_dispvars->menu_width = width;
_dispvars->menu_height = height;
_dispvars->menu_pitch = width * (rgb32 ? 4 : 2);
dispmanx_surface_setup(_dispvars, /* If menu is active in this frame but out menu surface is NULL, we allocate a new one.*/
width, if (_dispvars->menu_surface == NULL)
height, {
_dispvars->menu_pitch, _dispvars->menu_width = width;
rgb32 ? 32 : 16, _dispvars->menu_height = height;
VC_IMAGE_RGBA16, _dispvars->menu_pitch = width * (rgb32 ? 4 : 2);
210,
_dispvars->aspect, dispmanx_surface_setup(_dispvars,
3, width,
0, height,
&_dispvars->menu_surface); _dispvars->menu_pitch,
} rgb32 ? 32 : 16,
/* We update the menu surface if menu is active. */ VC_IMAGE_RGBA16,
dispmanx_surface_update(_dispvars, frame, _dispvars->menu_surface); 210,
_dispvars->aspect,
3,
0,
&_dispvars->menu_surface);
} }
/* We update the menu surface if menu is active. */
dispmanx_surface_update(_dispvars, frame, _dispvars->menu_surface);
} }
static void dispmanx_gfx_set_nonblock_state(void *data, bool state) static void dispmanx_gfx_set_nonblock_state(void *data, bool state)
@ -501,15 +508,15 @@ static bool dispmanx_gfx_focus(void *data)
static void dispmanx_gfx_viewport_info(void *data, struct video_viewport *vp) static void dispmanx_gfx_viewport_info(void *data, struct video_viewport *vp)
{ {
struct dispmanx_video *vid = data; struct dispmanx_video *vid = data;
if (!vid) if (!vid)
return; return;
vp->x = vp->y = 0; vp->x = vp->y = 0;
vp->width = vp->full_width = vid->core_width; vp->width = vp->full_width = vid->core_width;
vp->height = vp->full_height = vid->core_height; vp->height = vp->full_height = vid->core_height;
} }
static bool dispmanx_gfx_suppress_screensaver(void *data, bool enable) static bool dispmanx_gfx_suppress_screensaver(void *data, bool enable)
@ -528,7 +535,7 @@ static bool dispmanx_gfx_has_windowed(void *data)
} }
static bool dispmanx_gfx_set_shader(void *data, static bool dispmanx_gfx_set_shader(void *data,
enum rarch_shader_type type, const char *path) enum rarch_shader_type type, const char *path)
{ {
(void)data; (void)data;
(void)type; (void)type;
@ -556,38 +563,40 @@ static void dispmanx_set_aspect_ratio (void *data, unsigned aspect_ratio_idx)
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
/* Here we obtain the new aspect ratio. */ /* Here we obtain the new aspect ratio. */
float new_aspect = aspectratio_lut[aspect_ratio_idx].value; float new_aspect = aspectratio_lut[aspect_ratio_idx].value;
if (_dispvars->aspect != new_aspect) { if (_dispvars->aspect != new_aspect)
{
_dispvars->aspect = new_aspect; _dispvars->aspect = new_aspect;
if (_dispvars->main_surface != NULL) { if (_dispvars->main_surface != NULL)
dispmanx_surface_free(_dispvars, &_dispvars->main_surface); dispmanx_surface_free(_dispvars, &_dispvars->main_surface);
}
dispmanx_surface_setup(_dispvars,
_dispvars->core_width,
_dispvars->core_height,
_dispvars->core_pitch,
_dispvars->rgb32 ? 32 : 16,
_dispvars->rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565,
255,
_dispvars->aspect,
3,
0,
&_dispvars->main_surface);
if (_dispvars->menu_active) { dispmanx_surface_setup(_dispvars,
if (_dispvars->menu_surface != NULL) { _dispvars->core_width,
dispmanx_surface_free(_dispvars, &_dispvars->menu_surface); _dispvars->core_height,
} _dispvars->core_pitch,
dispmanx_surface_setup(_dispvars, _dispvars->rgb32 ? 32 : 16,
_dispvars->menu_width, _dispvars->rgb32 ? VC_IMAGE_XRGB8888 : VC_IMAGE_RGB565,
_dispvars->menu_height, 255,
_dispvars->menu_pitch, _dispvars->aspect,
16, 3,
VC_IMAGE_RGBA16, 0,
210, &_dispvars->main_surface);
_dispvars->aspect,
3, if (_dispvars->menu_active)
0, {
&_dispvars->menu_surface); if (_dispvars->menu_surface != NULL)
dispmanx_surface_free(_dispvars, &_dispvars->menu_surface);
dispmanx_surface_setup(_dispvars,
_dispvars->menu_width,
_dispvars->menu_height,
_dispvars->menu_pitch,
16,
VC_IMAGE_RGBA16,
210,
_dispvars->aspect,
3,
0,
&_dispvars->menu_surface);
} }
} }
} }
@ -611,7 +620,7 @@ static const video_poke_interface_t dispmanx_poke_interface = {
}; };
static void dispmanx_gfx_get_poke_interface(void *data, static void dispmanx_gfx_get_poke_interface(void *data,
const video_poke_interface_t **iface) const video_poke_interface_t **iface)
{ {
(void)data; (void)data;
*iface = &dispmanx_poke_interface; *iface = &dispmanx_poke_interface;
@ -620,9 +629,14 @@ static void dispmanx_gfx_get_poke_interface(void *data,
static void dispmanx_gfx_free(void *data) static void dispmanx_gfx_free(void *data)
{ {
struct dispmanx_video *_dispvars = data; struct dispmanx_video *_dispvars = data;
if (!_dispvars)
return;
dispmanx_surface_free(_dispvars, &_dispvars->main_surface); dispmanx_surface_free(_dispvars, &_dispvars->main_surface);
dispmanx_surface_free(_dispvars, &_dispvars->back_surface); dispmanx_surface_free(_dispvars, &_dispvars->back_surface);
if (_dispvars->menu_surface != NULL)
if (_dispvars->menu_surface)
dispmanx_surface_free(_dispvars, &_dispvars->menu_surface); dispmanx_surface_free(_dispvars, &_dispvars->menu_surface);
/* Close display and deinitialize. */ /* Close display and deinitialize. */
@ -654,8 +668,8 @@ video_driver_t video_dispmanx = {
dispmanx_gfx_read_viewport, dispmanx_gfx_read_viewport,
NULL, /* read_frame_raw */ NULL, /* read_frame_raw */
#ifdef HAVE_OVERLAY #ifdef HAVE_OVERLAY
NULL, /* overlay_interface */ NULL, /* overlay_interface */
#endif #endif
dispmanx_gfx_get_poke_interface dispmanx_gfx_get_poke_interface
}; };