big Raspberry Pi-related changes

* convert old rpi video driver into a generic OpenVG driver
* add VideoCore EGL context
* build GLES by default if VideoCore detected (currently does not run)
This commit is contained in:
Toad King 2012-09-18 19:41:58 -04:00
parent 580cf1c07e
commit 012c7def7b
9 changed files with 324 additions and 143 deletions

View File

@ -158,6 +158,10 @@ ifeq ($(HAVE_SDL), 1)
OBJ += gfx/context/drm_egl_ctx.o
DEFINES += $(GBM_CFLAGS) $(DRM_CFLAGS) $(EGL_CFLAGS)
LIBS += $(GBM_LIBS) $(DRM_LIBS) $(EGL_LIBS)
else ifeq ($(HAVE_VIDEOCORE), 1)
OBJ += gfx/context/vc_egl_ctx.o
# videocore's libEGL needs libGLESv2 linked as well
LIBS += -lGLESv2 -lEGL
else ifeq ($(HAVE_GLES), 1)
OBJ += gfx/context/xegl_ctx.o
DEFINES += $(EGL_CFLAGS)
@ -177,7 +181,7 @@ ifeq ($(HAVE_SDL), 1)
endif
endif
ifeq ($(HAVE_RPI), 1)
ifeq ($(HAVE_VIDEOCORE), 1)
OBJ += gfx/rpi.o
LIBS += -lOpenVG -lGLESv2 -lEGL -lbcm_host -lvcos -lvchiq_arm
endif

View File

@ -68,7 +68,7 @@ enum
INPUT_NULL
};
#if defined(HAVE_RPI)
#if defined(HAVE_VIDEOCORE)
#define VIDEO_DEFAULT_DRIVER VIDEO_RPI
#elif defined(HAVE_OPENGL) || defined(__CELLOS_LV2__)
#define VIDEO_DEFAULT_DRIVER VIDEO_GL

View File

@ -100,7 +100,7 @@ static const video_driver_t *video_drivers[] = {
#ifdef GEKKO
&video_gx,
#endif
#ifdef HAVE_RPI
#ifdef HAVE_VIDEOCORE
&video_rpi,
#endif
&video_null,

View File

@ -418,16 +418,6 @@ bool gfx_ctx_init(void)
if (!eglInitialize(g_egl_dpy, &major, &minor))
goto error;
#ifdef HAVE_OPENGLES2
RARCH_LOG("[KMS/EGL]: Using OpenGL ES API.\n");
if (!eglBindAPI(EGL_OPENGL_ES_API))
goto error;
#else
RARCH_LOG("[KMS/EGL]: Using OpenGL API.\n");
if (!eglBindAPI(EGL_OPENGL_API))
goto error;
#endif
EGLint n;
if (!eglChooseConfig(g_egl_dpy, config_attribs, &g_config, 1, &n) || n != 1)
goto error;

259
gfx/context/vc_egl_ctx.c Normal file
View File

@ -0,0 +1,259 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* 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 <http://www.gnu.org/licenses/>.
*/
// KMS/DRM context, running without any window manager.
// Based on kmscube example by Rob Clark.
#include "../../driver.h"
#include "../gfx_context.h"
#include "../gl_common.h"
#include "../gfx_common.h"
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <unistd.h>
#include <sched.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <bcm_host.h>
static EGLContext g_egl_ctx;
static EGLSurface g_egl_surf;
static EGLDisplay g_egl_dpy;
static EGLConfig g_config;
static volatile sig_atomic_t g_quit;
static bool g_inited;
static unsigned g_fb_width; // Just use something for now.
static unsigned g_fb_height;
struct drm_fb
{
struct gbm_bo *bo;
uint32_t fb_id;
};
static void sighandler(int sig)
{
(void)sig;
g_quit = 1;
}
void gfx_ctx_set_swap_interval(unsigned interval, bool inited)
{
eglSwapInterval(g_egl_dpy, interval);
}
void gfx_ctx_check_window(bool *quit,
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
{
(void)frame_count;
(void)width;
(void)height;
*resize = false;
*quit = g_quit;
}
void gfx_ctx_swap_buffers(void)
{
eglSwapBuffers(g_egl_dpy, g_egl_surf);
}
void gfx_ctx_set_resize(unsigned width, unsigned height)
{
(void)width;
(void)height;
}
void gfx_ctx_update_window_title(bool reset)
{
(void)reset;
}
void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
{
*width = g_fb_width;
*height = g_fb_height;
}
bool gfx_ctx_init(void)
{
if (g_inited)
{
RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
return false;
}
int32_t success;
EGLBoolean result;
EGLint num_config;
static EGL_DISPMANX_WINDOW_T nativewindow;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
DISPMANX_MODEINFO_T dispman_modeinfo;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
static const EGLint attribute_list[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
bcm_host_init();
// get an EGL display connection
g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
rarch_assert(g_egl_dpy != EGL_NO_DISPLAY);
// initialize the EGL display connection
result = eglInitialize(g_egl_dpy, NULL, NULL);
rarch_assert(result != EGL_FALSE);
// get an appropriate EGL frame buffer configuration
result = eglChooseConfig(g_egl_dpy, attribute_list, &g_config, 1, &num_config);
rarch_assert(result != EGL_FALSE);
// create an EGL rendering context
g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, NULL);
rarch_assert(g_egl_ctx != EGL_NO_CONTEXT);
// create an EGL window surface
success = graphics_get_display_size(0 /* LCD */, &g_fb_width, &g_fb_height);
rarch_assert(success >= 0);
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = g_fb_width;
dst_rect.height = g_fb_height;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = g_fb_width << 16;
src_rect.height = g_fb_height << 16;
dispman_display = vc_dispmanx_display_open(0 /* LCD */);
vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
dispman_update = vc_dispmanx_update_start(0);
dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
0 /*layer*/, &dst_rect, 0 /*src*/,
&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0 /*clamp*/, DISPMANX_NO_ROTATE);
nativewindow.element = dispman_element;
nativewindow.width = g_fb_width;
nativewindow.height = g_fb_height;
vc_dispmanx_update_submit_sync(dispman_update);
g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, &nativewindow, NULL);
rarch_assert(g_egl_surf != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx);
rarch_assert(result != EGL_FALSE);
return true;
}
bool gfx_ctx_set_video_mode(
unsigned width, unsigned height,
unsigned bits, bool fullscreen)
{
(void)bits;
if (g_inited)
return false;
struct sigaction sa = {{0}};
sa.sa_handler = sighandler;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
g_inited = true;
return true;
}
void gfx_ctx_destroy(void)
{
if (g_egl_dpy)
{
if (g_egl_ctx)
{
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(g_egl_dpy, g_egl_ctx);
}
if (g_egl_surf)
eglDestroySurface(g_egl_dpy, g_egl_surf);
eglTerminate(g_egl_dpy);
}
g_egl_ctx = NULL;
g_egl_surf = NULL;
g_egl_dpy = NULL;
g_config = 0;
g_inited = false;
}
void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
{
void *linuxinput = input_linuxraw.init();
*input = linuxinput ? &input_linuxraw : NULL;
*input_data = linuxinput;
}
void gfx_ctx_set_projection(gl_t *gl, const struct gl_ortho *ortho, bool allow_rotate)
{
// Calculate projection.
math_matrix proj;
matrix_ortho(&proj, ortho->left, ortho->right,
ortho->bottom, ortho->top, ortho->znear, ortho->zfar);
if (allow_rotate)
{
math_matrix rot;
matrix_rotate_z(&rot, M_PI * gl->rotation / 180.0f);
matrix_multiply(&proj, &rot, &proj);
}
gl->mvp = proj;
}
bool gfx_ctx_window_has_focus(void)
{
return g_inited;
}
gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
{
return eglGetProcAddress(symbol);
}

View File

@ -299,9 +299,6 @@ bool gfx_ctx_set_video_mode(
CWBorderPixel | CWColormap | CWEventMask, &swa);
XSetWindowBackground(g_dpy, g_win, 0);
if (!eglBindAPI(EGL_OPENGL_ES_API))
goto error;
g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, egl_ctx_attribs);
if (!g_egl_ctx)
goto error;

View File

@ -26,6 +26,10 @@
#include "config.h"
#endif
#ifdef HAVE_EGL
#include <EGL/egl.h>
#endif
#include "gl_common.h"
#include "gl_font.h"
#include "gfx_common.h"
@ -1246,6 +1250,16 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
if (!gl)
return NULL;
#ifdef HAVE_EGL
#ifdef HAVE_OPENGL_MODERN
if (!eglBindAPI(EGL_OPENGL_API))
return NULL;
#elif defined (HAVE_OPENGLES)
if (!eglBindAPI(EGL_OPENGL_ES_API))
return NULL;
#endif
#endif
if (!gfx_ctx_init())
{
free(gl);

153
gfx/rpi.c
View File

@ -1,7 +1,7 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2012 - Michael Lelli
*
*
* 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.
@ -15,16 +15,12 @@
*/
#include <math.h>
#include <unistd.h>
#include <signal.h>
#include <bcm_host.h>
#include <VG/openvg.h>
#include <VG/vgu.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "gfx_context.h"
#include "../libretro.h"
#include "../general.h"
#include "../input/linuxraw_input.h"
#include "../driver.h"
#ifdef HAVE_FREETYPE
@ -34,9 +30,6 @@
typedef struct
{
EGLDisplay mDisplay;
EGLSurface mSurface;
EGLContext mContext;
uint32_t mScreenWidth;
uint32_t mScreenHeight;
float mScreenAspect;
@ -46,6 +39,7 @@ typedef struct
unsigned mRenderWidth;
unsigned mRenderHeight;
unsigned x1, y1, x2, y2;
unsigned frame_count;
VGImageFormat mTexType;
VGImage mImage;
VGfloat mTransformMatrix[9];
@ -64,110 +58,40 @@ typedef struct
#endif
} rpi_t;
static volatile sig_atomic_t rpi_shutdown = 0;
static void rpi_kill(int sig)
{
(void)sig;
rpi_shutdown = 1;
}
static void rpi_set_nonblock_state(void *data, bool state)
{
rpi_t *rpi = (rpi_t*)data;
eglSwapInterval(rpi->mDisplay, state ? 0 : 1);
(void)data;
gfx_ctx_set_swap_interval(state ? 0 : 1, true);
}
static void *rpi_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
int32_t success;
EGLBoolean result;
EGLint num_config;
rpi_t *rpi = (rpi_t*)calloc(1, sizeof(rpi_t));
*input = NULL;
if (!rpi)
return NULL;
static EGL_DISPMANX_WINDOW_T nativewindow;
if (!eglBindAPI(EGL_OPENVG_API))
return NULL;
DISPMANX_ELEMENT_HANDLE_T dispman_element;
DISPMANX_DISPLAY_HANDLE_T dispman_display;
DISPMANX_UPDATE_HANDLE_T dispman_update;
DISPMANX_MODEINFO_T dispman_modeinfo;
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
static const EGLint attribute_list[] =
if (!gfx_ctx_init())
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
free(rpi);
return NULL;
}
EGLConfig config;
gfx_ctx_get_video_size(&rpi->mScreenWidth, &rpi->mScreenHeight);
RARCH_LOG("Detecting screen resolution %ux%u.\n", rpi->mScreenWidth, rpi->mScreenHeight);
bcm_host_init();
// get an EGL display connection
rpi->mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
rarch_assert(rpi->mDisplay != EGL_NO_DISPLAY);
// initialize the EGL display connection
result = eglInitialize(rpi->mDisplay, NULL, NULL);
rarch_assert(result != EGL_FALSE);
eglBindAPI(EGL_OPENVG_API);
// get an appropriate EGL frame buffer configuration
result = eglChooseConfig(rpi->mDisplay, attribute_list, &config, 1, &num_config);
rarch_assert(result != EGL_FALSE);
// create an EGL rendering context
rpi->mContext = eglCreateContext(rpi->mDisplay, config, EGL_NO_CONTEXT, NULL);
rarch_assert(rpi->mContext != EGL_NO_CONTEXT);
// create an EGL window surface
success = graphics_get_display_size(0 /* LCD */, &rpi->mScreenWidth, &rpi->mScreenHeight);
rarch_assert(success >= 0);
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.width = rpi->mScreenWidth;
dst_rect.height = rpi->mScreenHeight;
src_rect.x = 0;
src_rect.y = 0;
src_rect.width = rpi->mScreenWidth << 16;
src_rect.height = rpi->mScreenHeight << 16;
dispman_display = vc_dispmanx_display_open(0 /* LCD */);
vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
dispman_update = vc_dispmanx_update_start(0);
dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
0 /*layer*/, &dst_rect, 0 /*src*/,
&src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0 /*clamp*/, DISPMANX_NO_ROTATE);
nativewindow.element = dispman_element;
nativewindow.width = rpi->mScreenWidth;
nativewindow.height = rpi->mScreenHeight;
vc_dispmanx_update_submit_sync(dispman_update);
rpi->mSurface = eglCreateWindowSurface(rpi->mDisplay, config, &nativewindow, NULL);
rarch_assert(rpi->mSurface != EGL_NO_SURFACE);
// connect the context to the surface
result = eglMakeCurrent(rpi->mDisplay, rpi->mSurface, rpi->mSurface, rpi->mContext);
rarch_assert(result != EGL_FALSE);
gfx_ctx_set_swap_interval(video->vsync ? 1 : 0, false);
rpi->mTexType = video->rgb32 ? VG_sABGR_8888 : VG_sARGB_1555;
rpi->mKeepAspect = video->force_aspect;
// check for SD televisions: they should always be 4:3
if (dispman_modeinfo.width == 720 && (dispman_modeinfo.height == 480 || dispman_modeinfo.height == 576))
if (rpi->mScreenWidth == 720 && (rpi->mScreenHeight == 480 || rpi->mScreenHeight == 576))
rpi->mScreenAspect = 4.0f / 3.0f;
else
rpi->mScreenAspect = (float)dispman_modeinfo.width / dispman_modeinfo.height;
rpi->mScreenAspect = (float)rpi->mScreenWidth / rpi->mScreenHeight;
VGfloat clearColor[4] = {0, 0, 0, 1};
vgSetfv(VG_CLEAR_COLOR, 4, clearColor);
@ -182,12 +106,7 @@ static void *rpi_init(const video_info_t *video, const input_driver_t **input, v
video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED);
rpi_set_nonblock_state(rpi, !video->vsync);
linuxraw_input_t *linuxraw_input = (linuxraw_input_t*)input_linuxraw.init();
if (linuxraw_input)
{
*input = (const input_driver_t *)&input_linuxraw;
*input_data = linuxraw_input;
}
gfx_ctx_input_driver(input, input_data);
#ifdef HAVE_FREETYPE
if (g_settings.video.font_enable)
@ -219,13 +138,6 @@ static void *rpi_init(const video_info_t *video, const input_driver_t **input, v
}
#endif
struct sigaction sa;
sa.sa_handler = rpi_kill;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
return rpi;
}
@ -245,11 +157,7 @@ static void rpi_free(void *data)
}
#endif
// Release EGL resources
eglMakeCurrent(rpi->mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(rpi->mDisplay, rpi->mSurface);
eglDestroyContext(rpi->mDisplay, rpi->mContext);
eglTerminate(rpi->mDisplay);
gfx_ctx_destroy();
free(rpi);
}
@ -385,6 +293,7 @@ static void rpi_calculate_quad(rpi_t *rpi)
static bool rpi_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
{
rpi_t *rpi = (rpi_t*)data;
rpi->frame_count++;
if (width != rpi->mRenderWidth || height != rpi->mRenderHeight)
{
@ -407,27 +316,35 @@ static bool rpi_frame(void *data, const void *frame, unsigned width, unsigned he
vgDrawImage(rpi->mImage);
#ifdef HAVE_FREETYPE
if (msg && rpi->mFontsOn)
rpi_draw_message(rpi, msg);
//if (msg && rpi->mFontsOn)
// rpi_draw_message(rpi, msg);
static char temp[4096];
gfx_window_title(temp, 4096);
rpi_draw_message(rpi, temp);
#else
(void)msg;
#endif
eglSwapBuffers(rpi->mDisplay, rpi->mSurface);
gfx_ctx_swap_buffers();
return true;
}
static bool rpi_alive(void *data)
{
(void)data;
return !rpi_shutdown;
rpi_t *rpi = (rpi_t*)data;
bool quit, resize;
gfx_ctx_check_window(&quit,
&resize, &rpi->mScreenWidth, &rpi->mScreenHeight,
rpi->frame_count);
return !quit;
}
static bool rpi_focus(void *data)
{
(void)data;
return true;
return gfx_ctx_window_has_focus();
}
const video_driver_t video_rpi = {

View File

@ -2,6 +2,7 @@ check_switch_c C99 -std=gnu99 "Cannot find C99 compatible compiler."
check_switch_c NOUNUSED -Wno-unused-result
add_define_make NOUNUSED "$HAVE_NOUNUSED"
HAVE_EGL=no
# There are still broken 64-bit Linux distros out there. :)
[ -d /usr/lib64 ] && add_library_dirs /usr/lib64
@ -11,14 +12,12 @@ add_define_make NOUNUSED "$HAVE_NOUNUSED"
if [ "$OS" = 'BSD' ]; then DYLIB=-lc; else DYLIB=-ldl; fi
[ -d /opt/vc/lib ] && add_library_dirs /opt/vc/lib
check_lib RPI -lbcm_host bcm_host_init "-lvcos -lvchiq_arm"
check_lib VIDEOCORE -lbcm_host bcm_host_init "-lvcos -lvchiq_arm"
if [ "$HAVE_RPI" = 'yes' ]; then
if [ "$HAVE_VIDEOCORE" = 'yes' ]; then
[ -d /opt/vc/include ] && add_include_dirs /opt/vc/include
[ -d /opt/vc/include/interface/vcos/pthreads ] && add_include_dirs /opt/vc/include/interface/vcos/pthreads
# the gles library gets messed up with the gl library if available, so turn it off
HAVE_OPENGL='no'
HAVE_GLES='yes'
fi
if [ "$LIBRETRO" ]; then
@ -128,7 +127,6 @@ fi
check_lib DYNAMIC "$DYLIB" dlopen
HAVE_EGL=no
if [ "$HAVE_KMS" = "yes" ]; then
check_pkgconf GBM gbm
check_pkgconf DRM libdrm
@ -140,8 +138,10 @@ if [ "$HAVE_KMS" = "yes" ]; then
fi
[ "$HAVE_GLES" = "yes" ] && HAVE_EGL=yes
check_pkgconf EGL egl
check_pkgconf GLES glesv2
if [ "$HAVE_VIDEOCORE" != "yes" ]; then
check_pkgconf EGL egl
check_pkgconf GLES glesv2
fi
check_pkgconf FREETYPE freetype2
check_pkgconf X11 x11
@ -160,6 +160,6 @@ check_pkgconf PYTHON python3
add_define_make OS "$OS"
# Creates config.mk and config.h.
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL GLES EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE LIBPNG DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO PBO STRL 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 SINC FIXED_POINT BSV_MOVIE RPI"
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL GLES EGL KMS GBM DRM DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE LIBPNG DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY NETWORK_CMD STDIN_CMD COMMAND SOCKET_LEGACY FBO PBO STRL 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 SINC FIXED_POINT BSV_MOVIE VIDEOCORE"
create_config_make config.mk $VARS
create_config_header config.h $VARS