diff --git a/Makefile.common b/Makefile.common index eed328a7c2..2c70757c9a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -515,6 +515,12 @@ ifeq ($(HAVE_EXYNOS), 1) DEFINES += $(DRM_CFLAGS) $(EXYNOS_CFLAGS) endif +ifeq ($(HAVE_DISPMANX), 1) + OBJ += gfx/drivers/dispmanx_gfx.o + LIBS += $(DISPMANX_LIBS) + DEFINES += $(DISPMANX_CFLAGS) +endif + ifeq ($(HAVE_SUNXI), 1) OBJ += gfx/drivers/sunxi_gfx.o gfx/pixman/pixman-arm-neon-asm.o endif diff --git a/config.def.h b/config.def.h index 274ed32739..58f03cc018 100644 --- a/config.def.h +++ b/config.def.h @@ -44,6 +44,7 @@ enum VIDEO_OMAP, VIDEO_EXYNOS, VIDEO_SUNXI, + VIDEO_DISPMANX, AUDIO_RSOUND, AUDIO_OSS, diff --git a/gfx/drivers/dispmanx_gfx.c b/gfx/drivers/dispmanx_gfx.c new file mode 100644 index 0000000000..5dcc9d7efd --- /dev/null +++ b/gfx/drivers/dispmanx_gfx.c @@ -0,0 +1,681 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2015 - Manuel Alfayate + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "../../driver.h" +#include +#include +#include "../../general.h" +#include "../../retroarch.h" +#include +#include "../video_viewport.h" +#include "../video_monitor.h" +#include "../video_context_driver.h" +#include "../font_renderer_driver.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define numpages 2 + +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; + VC_RECT_T srcRect; + VC_RECT_T dstRect; + VC_RECT_T bmpRect; + unsigned int vcImagePtr; + unsigned int screen; + unsigned int pitch; + unsigned int flipPage; + + // Internal frame dimensions + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; + // Some cores render things we don't need between scanlines + unsigned int visible_width; + + bool aspectRatioCorrection; + void *pixmem; + + struct dispmanx_page *pages; + struct dispmanx_page *currentPage; + unsigned int pageflip_pending; + + // For console blanking + int fd; + char *fbp; + unsigned int screensize; + char *screen_bck; + + // For threading + pthread_cond_t vsync_condition; + pthread_mutex_t pending_mutex; + + // Mutex to isolate the vsync condition signaling + pthread_mutex_t vsync_cond_mutex; + + // Menu + bool menu_active; + DISPMANX_ELEMENT_HANDLE_T menu_element; + DISPMANX_RESOURCE_HANDLE_T menu_resources[2]; + VC_IMAGE_TYPE_T menu_pixFormat; + VC_DISPMANX_ALPHA_T *menu_alpha; + VC_RECT_T menu_srcRect; + VC_RECT_T menu_dstRect; + VC_RECT_T menu_bmpRect; + unsigned int menu_width; + unsigned int menu_height; + unsigned int menu_pitch; + unsigned int menu_flip_page; + + // External aspect ratio + float aspect; +}; + +struct dispmanx_page { + unsigned int numpage; + struct dispmanx_page *next; + // This field will allow me 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. + pthread_mutex_t page_used_mutex; + bool used; +}; + +void dispmanx_blank_console(void *data) { + struct dispmanx_video *_dispvars = data; + + struct fb_var_screeninfo vinfo; + unsigned int fb_bytes_per_pixel; + + _dispvars->fd = open("/dev/fb0", O_RDWR); + + // We need this just to know the framebuffer color depth, which vc_get_display_info() doesn't provide. + ioctl(_dispvars->fd, FBIOGET_VSCREENINFO, &vinfo); + fb_bytes_per_pixel = vinfo.bits_per_pixel / 8; + + _dispvars->screensize = _dispvars->amode.width * _dispvars->amode.height * fb_bytes_per_pixel; + _dispvars->fbp = (char *)mmap(0, _dispvars->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, _dispvars->fd, 0); + + // Disable cursor blinking + system("setterm -cursor off"); + + // Backup console screen contents + _dispvars->screen_bck = (char*)malloc(_dispvars->screensize * sizeof(char)); + memcpy((char*)_dispvars->screen_bck, (char*)_dispvars->fbp, _dispvars->screensize); + + // Blank console + memset((char*)(_dispvars->fbp), 0x00, _dispvars->screensize); + + // Unmap and close + munmap(&_dispvars->fd, _dispvars->screensize); + close (_dispvars->fd); +} + +void dispmanx_unblank_console(void *data) { + struct dispmanx_video *_dispvars = data; + + _dispvars->fd = open("/dev/fb0", O_RDWR); + _dispvars->fbp = (char *)mmap(0, _dispvars->screensize, PROT_READ | PROT_WRITE, MAP_SHARED, _dispvars->fd, 0); + + // Restore console screen contents + memcpy((char*)_dispvars->fbp, (char*)_dispvars->screen_bck, _dispvars->screensize); + free(_dispvars->screen_bck); + + // Unmap and close + munmap(&_dispvars->fd, _dispvars->screensize); + close (_dispvars->fd); + + // Restore cursor blinking + 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) +{ + struct dispmanx_video *_dispvars = data; + struct dispmanx_page *page = NULL; + unsigned i; + + while (page == NULL) { + // 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 ATM, wait until a free page is freed by vsync CB + if (page == NULL) { + pthread_mutex_lock (&_dispvars->vsync_cond_mutex); + pthread_cond_wait (&_dispvars->vsync_condition, &_dispvars->vsync_cond_mutex); + pthread_mutex_unlock (&_dispvars->vsync_cond_mutex); + } + } + + pthread_mutex_lock (&page->page_used_mutex); + page->used = true; + pthread_mutex_unlock (&page->page_used_mutex); + + return page; +} + +void vsync_callback (DISPMANX_UPDATE_HANDLE_T u, void *data){ + struct dispmanx_page *page = data; + + // We signal the vsync condition, just in case we're waiting for it somewhere (no free pages, etc) + pthread_mutex_lock(&page->dispvars->vsync_cond_mutex); + pthread_cond_signal(&page->dispvars->vsync_condition); + pthread_mutex_unlock(&page->dispvars->vsync_cond_mutex); + + pthread_mutex_lock(&page->dispvars->pending_mutex); + page->dispvars->pageflip_pending--; + pthread_mutex_unlock(&page->dispvars->pending_mutex); + + // We mark as free the page that was visible until now + if (page->dispvars->currentPage != NULL) { + pthread_mutex_lock (&page->page_used_mutex); + page->dispvars->currentPage->used = false; + pthread_mutex_unlock (&page->page_used_mutex); + } + + // The page on which we just issued the flip that caused this callback becomes the visible one + page->dispvars->currentPage = page; +} + +void dispmanx_flip (struct dispmanx_page *page, void *data) { + struct dispmanx_video *_dispvars = data; + + // Dispmanx doesn't support issuing more than one pageflip. If we do, the second CB isn't called. + if (_dispvars->pageflip_pending > 0) { + pthread_mutex_lock(&_dispvars->vsync_cond_mutex); + pthread_cond_wait (&_dispvars->vsync_condition, &_dispvars->vsync_cond_mutex); + pthread_mutex_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); + + pthread_mutex_lock(&_dispvars->pending_mutex); + _dispvars->pageflip_pending++; + pthread_mutex_unlock(&_dispvars->pending_mutex); +} + +void dispmanx_free_main_resources(void *data) { + struct dispmanx_video *_dispvars = data; + int i; + + _dispvars->update = vc_dispmanx_update_start(0); + + for (i = 0; i < numpages; i++) + vc_dispmanx_resource_delete(_dispvars->resources[i]); + + vc_dispmanx_element_remove(_dispvars->update, _dispvars->element ); + + vc_dispmanx_update_submit_sync(_dispvars->update); +} + +bool dispmanx_setup_scale (void *data, unsigned width, unsigned height, unsigned pitch) { + struct dispmanx_video *_dispvars = data; + int i; + + // Since internal frame resoluton seems to have changed, We change the internal frame resolution + // in use, and call again dispmanx_setup_scale() to set the rects, etc + _dispvars->width = width; + _dispvars->height = height; + + // Total pitch, including things the cores render between "visible" scanlines + _dispvars->pitch = pitch; + + // The "visible" width obtained from the core pitch + _dispvars->visible_width = pitch / _dispvars->bytes_per_pixel; + + dispmanx_free_main_resources (_dispvars); + vc_dispmanx_display_get_info(_dispvars->display, &(_dispvars->amode)); + + // We chose the pixel format depending on the bpp of the frame + switch (_dispvars->bytes_per_pixel) { + case 2: + _dispvars->pixFormat = VC_IMAGE_RGB565; + break; + case 4: + _dispvars->pixFormat = VC_IMAGE_XRGB8888; + break; + default: + RARCH_ERR("video_dispmanx: wrong pixel format\n"); + return NULL; + } + // Transparency disabled + VC_DISPMANX_ALPHA_T layerAlpha; + layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; + layerAlpha.opacity = 255; + layerAlpha.mask = 0; + _dispvars->alpha = &layerAlpha; + + switch (g_settings.video.aspect_ratio_idx){ + case ASPECT_RATIO_4_3: + _dispvars->aspect = (float)4 / (float)3; + break; + case ASPECT_RATIO_16_9: + _dispvars->aspect = (float)16 / (float)9; + break; + case ASPECT_RATIO_16_10: + _dispvars->aspect = (float)16 / (float)10; + break; + case ASPECT_RATIO_16_15: + _dispvars->aspect = (float)16 / (float)15; + break; + case ASPECT_RATIO_CORE: + _dispvars->aspect = (float)_dispvars->width / (float)_dispvars->height; + break; + default: + _dispvars->aspect = (float)_dispvars->width / (float)_dispvars->height; + break; + } + + int dst_width = _dispvars->amode.height * _dispvars->aspect; + + // If we obtain an scaled image width that is bigger than the physical screen width, + // then we keep the physical screen width as our maximun width. + //if (dst_width > _dispvars->amode.width) + // dst_width = _dispvars->amode.width; + int dst_ypos = (_dispvars->amode.width - dst_width) / 2; + vc_dispmanx_rect_set(&(_dispvars->dstRect), dst_ypos, 0, + dst_width, _dispvars->amode.height); + + /*} else { + vc_dispmanx_rect_set(&(_dispvars->dstRect), 0, 0, + _dispvars->amode.width, _dispvars->amode.height); + }*/ + + // We configure the rects now + vc_dispmanx_rect_set(&(_dispvars->bmpRect), 0, 0, _dispvars->width, _dispvars->height); + vc_dispmanx_rect_set(&(_dispvars->srcRect), 0, 0, _dispvars->width << 16, _dispvars->height << 16); + + // We create as many resources as pages + for (i = 0; i < numpages; i++) + _dispvars->resources[i] = 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), + DISPMANX_PROTECTION_NONE, _dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0); + + vc_dispmanx_update_submit_sync(_dispvars->update); + + return true; +} + +void dispmanx_update_main (void *data, const void *frame) { + struct dispmanx_video *_dispvars = data; + + struct dispmanx_page *page; + page = dispmanx_get_free_page(_dispvars); + + // Frame blitting + vc_dispmanx_resource_write_data(_dispvars->resources[page->numpage], _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); + + return; +} + +static void *dispmanx_gfx_init(const video_info_t *video, + const input_driver_t **input, void **input_data) +{ + int i; + + struct dispmanx_video *_dispvars; + _dispvars = calloc(1, sizeof(struct dispmanx_video)); + + _dispvars->bytes_per_pixel = video->rgb32 ? 4 : 2; + _dispvars->screen = 0; + _dispvars->vcImagePtr = 0; + _dispvars->pages = calloc(numpages, sizeof(struct dispmanx_page)); + _dispvars->pageflip_pending = 0; + _dispvars->currentPage = NULL; + + for (i = 0; i < numpages; i++) { + _dispvars->pages[i].numpage = i; + _dispvars->pages[i].used = false; + _dispvars->pages[i].dispvars = _dispvars; + pthread_mutex_init(&_dispvars->pages[i].page_used_mutex, NULL); + } + + // Initialize the rest of the mutexes and conditions + pthread_cond_init(&_dispvars->vsync_condition, NULL); + pthread_mutex_init(&_dispvars->pending_mutex, NULL); + pthread_mutex_init(&_dispvars->vsync_cond_mutex, NULL); + + bcm_host_init(); + _dispvars->display = vc_dispmanx_display_open(_dispvars->screen); + + if (input && input_data) + *input = NULL; + + return _dispvars; +} + +static bool dispmanx_gfx_frame(void *data, const void *frame, unsigned width, + unsigned height, unsigned pitch, const char *msg) +{ + struct dispmanx_video *_dispvars = data; + + // Check if neither menu nor core framebuffer is to be displayed. + if (!_dispvars->menu_active && frame == NULL) + return true; + + if (width != _dispvars->width || height != _dispvars->height) + { + // Sanity check + if (width == 0 || height == 0) + return true; + + RARCH_LOG("video_dispmanx: internal frame resolution changed by core\n"); + + if (!dispmanx_setup_scale(_dispvars, width, height, pitch)) + { + RARCH_ERR("video_dispmanx: frame resolution set failed\n"); + return false; + } + dispmanx_blank_console (_dispvars); + } + + if (_dispvars->menu_active) { + 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 + dispmanx_update_main(_dispvars, frame); + + return true; +} + +static void dispmanx_free_menu_resources (void *data) { + struct dispmanx_video *_dispvars = 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_element_remove(_dispvars->update, _dispvars->menu_element ); + + vc_dispmanx_update_submit_sync(_dispvars->update); + + _dispvars->menu_width = 0; + _dispvars->menu_height = 0; +} + +static void dispmanx_set_texture_enable(void *data, bool state, bool full_screen) +{ + struct dispmanx_video *_dispvars = data; + if (_dispvars) + _dispvars->menu_active = state; + if (!_dispvars->menu_active) + dispmanx_free_menu_resources(_dispvars); +} + +static void dispmanx_set_texture_frame(void *data, const void *frame, bool rgb32, +unsigned width, unsigned height, float alpha) +{ + struct dispmanx_video *_dispvars = data; + + // If we're entering the menu in this frame, we must setup rects, resources and menu element. + if (width != _dispvars->menu_width || height != _dispvars->menu_height) { + + // Sanity check + if (width == 0 || height == 0) + return; + + int i; + + _dispvars->menu_width = width; + _dispvars->menu_height = height; + + _dispvars->menu_pitch = width * (rgb32 ? 4 : 2); + + _dispvars->menu_pixFormat = VC_IMAGE_RGBA16; + _dispvars->menu_flip_page = 0; + + // Transparency disabled + VC_DISPMANX_ALPHA_T layerAlpha; + layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; + //layerAlpha.opacity = (unsigned char)(255.0f * alpha); + layerAlpha.opacity = 210; + layerAlpha.mask = 0; + _dispvars->menu_alpha = &layerAlpha; + + int dst_width = _dispvars->amode.height * _dispvars->aspect; + + // If we obtain an scaled image width that is bigger than the physical screen width, + // then we keep the physical screen width as our maximun width. + //if (dst_width > _dispvars->amode.width) + // dst_width = _dispvars->amode.width; + int dst_ypos = (_dispvars->amode.width - dst_width) / 2; + vc_dispmanx_rect_set(&(_dispvars->menu_dstRect), dst_ypos, 0, + dst_width, _dispvars->amode.height); + + // We configure the rects now + 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, + _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), + 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 fn. 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], + _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. +} + +static void dispmanx_gfx_set_nonblock_state(void *data, bool state) +{ + struct dispmanx_video *vid = data; + + if (!data) + return; +} + +static bool dispmanx_gfx_alive(void *data) +{ + (void)data; + return true; /* always alive */ +} + +static bool dispmanx_gfx_focus(void *data) +{ + (void)data; + return true; /* fb device always has focus */ +} + +static void dispmanx_gfx_viewport_info(void *data, struct video_viewport *vp) +{ + struct dispmanx_video *vid = data; + + if (!vid) + return; + + vp->x = vp->y = 0; + + vp->width = vp->full_width = vid->width; + vp->height = vp->full_height = vid->height; +} + +static bool dispmanx_gfx_suppress_screensaver(void *data, bool enable) +{ + (void)data; + (void)enable; + +return false; +} + +static bool dispmanx_gfx_has_windowed(void *data) +{ + (void)data; + /* TODO - implement. */ + return true; +} + +static bool dispmanx_gfx_set_shader(void *data, +enum rarch_shader_type type, const char *path) +{ + (void)data; + (void)type; + (void)path; + + return false; +} + +static void dispmanx_gfx_set_rotation(void *data, unsigned rotation) +{ + (void)data; + (void)rotation; +} + +static bool dispmanx_gfx_read_viewport(void *data, uint8_t *buffer) +{ + (void)data; + (void)buffer; + + return true; +} + +static const video_poke_interface_t dispmanx_poke_interface = { + NULL, /* set_video_mode */ + NULL, /* set_filtering */ + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ +#ifdef HAVE_FBO + NULL, /* get_current_framebuffer */ +#endif + NULL, /* get_proc_address */ + NULL, /* dispmanx_set_aspect_ratio */ + NULL, /* dispmanx_apply_state_changes */ +#ifdef HAVE_MENU + dispmanx_set_texture_frame, + dispmanx_set_texture_enable, +#endif + NULL, /* dispmanx_set_osd_msg */ + NULL /* dispmanx_show_mouse */ +}; + +static void dispmanx_gfx_get_poke_interface(void *data, + const video_poke_interface_t **iface) +{ + (void)data; + *iface = &dispmanx_poke_interface; +} + +static void dispmanx_gfx_free(void *data) { + struct dispmanx_video *_dispvars = data; + int i; + + dispmanx_free_main_resources(_dispvars); + + // Close display and deinit + vc_dispmanx_display_close(_dispvars->display); + bcm_host_deinit(); + + // Destroy mutexes and conditions + pthread_mutex_destroy(&_dispvars->pending_mutex); + pthread_cond_destroy(&_dispvars->vsync_condition); + for (i = 0; i < numpages; i++) + pthread_mutex_destroy(&_dispvars->pages[i].page_used_mutex); + + free (_dispvars->pages); + + dispmanx_unblank_console(_dispvars); +} + +video_driver_t video_dispmanx = { + dispmanx_gfx_init, + dispmanx_gfx_frame, + dispmanx_gfx_set_nonblock_state, + dispmanx_gfx_alive, + dispmanx_gfx_focus, + dispmanx_gfx_suppress_screensaver, + dispmanx_gfx_has_windowed, + dispmanx_gfx_set_shader, + dispmanx_gfx_free, + "dispmanx", + + dispmanx_gfx_set_rotation, + dispmanx_gfx_viewport_info, + dispmanx_gfx_read_viewport, + +#ifdef HAVE_OVERLAY + NULL, /* overlay_interface */ +#endif + dispmanx_gfx_get_poke_interface +}; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index f74471ff42..1c378086c7 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -60,6 +60,9 @@ static const video_driver_t *video_drivers[] = { #ifdef HAVE_EXYNOS &video_exynos, #endif +#ifdef HAVE_DISPMANX + &video_dispmanx, +#endif #ifdef HAVE_SUNXI &video_sunxi, #endif diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 972454dfd4..972c373046 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -186,6 +186,7 @@ extern video_driver_t video_sdl2; extern video_driver_t video_vg; extern video_driver_t video_omap; extern video_driver_t video_exynos; +extern video_driver_t video_dispmanx; extern video_driver_t video_sunxi; extern video_driver_t video_null; diff --git a/qb/config.libs.sh b/qb/config.libs.sh index c497f18892..f55255f6bd 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -110,6 +110,11 @@ if [ "$HAVE_EXYNOS" != "no" ]; then check_pkgconf DRM libdrm fi +if [ "$HAVE_DISPMANX" != "no" ]; then + DISPMANX_LIBS="-L/opt/vc/lib -lbcm_host -lvcos -lvchiq_arm" + DISPMANX_INCLUDES="-I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux/ -I/opt/vc/include/interface/vcos/pthreads" +fi + if [ "$LIBRETRO" ]; then echo "Notice: Explicit libretro used, disabling dynamic libretro loading ..." HAVE_DYNAMIC='no' @@ -348,6 +353,6 @@ add_define_make OS "$OS" # Creates config.mk and config.h. add_define_make GLOBAL_CONFIG_DIR "$GLOBAL_CONFIG_DIR" -VARS="RGUI LAKKA GLUI XMB ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL SDL2 D3D9 DINPUT WINXINPUT DSOUND XAUDIO OPENGL EXYNOS SUNXI OMAP GLES GLES3 VG EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG LIBXML2 ZLIB DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE FREETYPE XKBCOMMON XVIDEO X11 XEXT XF86VM XINERAMA WAYLAND MALI_FBDEV VIVANTE_FBDEV NETWORKING NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO STRL STRCASESTR MMAP PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 BSV_MOVIE VIDEOCORE NEON FLOATHARD FLOATSOFTFP UDEV V4L2 AV_CHANNEL_LAYOUT 7ZIP PARPORT" +VARS="RGUI LAKKA GLUI XMB ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL SDL2 D3D9 DINPUT WINXINPUT DSOUND XAUDIO OPENGL EXYNOS DISPMANX SUNXI OMAP GLES GLES3 VG EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG LIBXML2 ZLIB DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE FREETYPE XKBCOMMON XVIDEO X11 XEXT XF86VM XINERAMA WAYLAND MALI_FBDEV VIVANTE_FBDEV NETWORKING NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO STRL STRCASESTR MMAP PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM FFMPEG_AVCODEC_ENCODE_AUDIO2 FFMPEG_AVCODEC_ENCODE_VIDEO2 BSV_MOVIE VIDEOCORE NEON FLOATHARD FLOATSOFTFP UDEV V4L2 AV_CHANNEL_LAYOUT 7ZIP PARPORT" create_config_make config.mk $VARS create_config_header config.h $VARS diff --git a/qb/config.params.sh b/qb/config.params.sh index c6bb3e6c67..940ac6c3b9 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -25,6 +25,7 @@ HAVE_OMAP=no # Enable OMAP video support HAVE_XINERAMA=auto # Disable Xinerama support. HAVE_KMS=auto # Enable KMS context support HAVE_EXYNOS=no # Enable Exynos video support +HAVE_DISPMANX=no # Enable Dispmanx video support HAVE_SUNXI=no # Enable Sunxi video support HAVE_EGL=auto # Enable EGL context support HAVE_VG=auto # Enable OpenVG support diff --git a/settings.c b/settings.c index 9d6a586c40..e147116027 100644 --- a/settings.c +++ b/settings.c @@ -156,6 +156,8 @@ const char *config_get_default_video(void) return "omap"; case VIDEO_EXYNOS: return "exynos"; + case VIDEO_DISPMANX: + return "dispmanx"; case VIDEO_SUNXI: return "sunxi"; default: