mirror of
https://github.com/libretro/RetroArch
synced 2025-03-28 08:37:41 +00:00
Add experimental X/EGL support.
This commit is contained in:
parent
d3b1780a66
commit
ff60bcb5e5
10
Makefile
10
Makefile
@ -124,7 +124,7 @@ ifeq ($(HAVE_COREAUDIO), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_SDL), 1)
|
||||
OBJ += gfx/sdl_gfx.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
|
||||
OBJ += gfx/sdl_gfx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
|
||||
OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o
|
||||
DEFINES += $(SDL_CFLAGS) $(BSD_LOCAL_INC)
|
||||
LIBS += $(SDL_LIBS)
|
||||
@ -143,10 +143,18 @@ endif
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
OBJ += gfx/gl.o gfx/fonts/freetype.o gfx/math/matrix.o
|
||||
|
||||
ifeq ($(OSX),1)
|
||||
LIBS += -framework OpenGL
|
||||
else
|
||||
ifeq ($(HAVE_GLES), 1)
|
||||
LIBS += -lGL -lGLESv2 -lEGL
|
||||
DEFINES += -DHAVE_OPENGLES -DHAVE_OPENGLES2
|
||||
OBJ += gfx/context/xegl_ctx.o
|
||||
else
|
||||
LIBS += -lGL
|
||||
OBJ += gfx/context/sdl_ctx.o
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -185,16 +185,6 @@ void gfx_ctx_swap_buffers(void)
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
bool gfx_ctx_key_pressed(int key)
|
||||
{
|
||||
int num_keys;
|
||||
Uint8 *keymap = SDL_GetKeyState(&num_keys);
|
||||
if (key >= num_keys)
|
||||
return false;
|
||||
|
||||
return keymap[key];
|
||||
}
|
||||
|
||||
// 1.2 specific workaround for tiling WMs. In 1.3 we call GetSize directly, so we don't need to rely on
|
||||
// proper event handling (I hope).
|
||||
#if !defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_X11)
|
||||
|
400
gfx/context/xegl_ctx.c
Normal file
400
gfx/context/xegl_ctx.c
Normal file
@ -0,0 +1,400 @@
|
||||
/* 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/>.
|
||||
*/
|
||||
|
||||
// X/EGL context. Mostly used for testing GLES code paths.
|
||||
// Should be its own file as it has lots of X11 stuff baked into it as well.
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../gfx_context.h"
|
||||
#include "../gl_common.h"
|
||||
#include "../gfx_common.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
static Display *g_dpy;
|
||||
static Window g_win;
|
||||
static Colormap g_cmap;
|
||||
static Atom g_quit_atom;
|
||||
static bool g_has_focus;
|
||||
|
||||
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_interval;
|
||||
|
||||
static void sighandler(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
g_quit = 1;
|
||||
}
|
||||
|
||||
static void hide_mouse(void)
|
||||
{
|
||||
Cursor no_ptr;
|
||||
Pixmap bm_no;
|
||||
XColor black, dummy;
|
||||
Colormap colormap;
|
||||
|
||||
static char bm_no_data[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
colormap = DefaultColormap(g_dpy, DefaultScreen(g_dpy));
|
||||
if (!XAllocNamedColor(g_dpy, colormap, "black", &black, &dummy))
|
||||
return;
|
||||
|
||||
bm_no = XCreateBitmapFromData(g_dpy, g_win, bm_no_data, 8, 8);
|
||||
no_ptr = XCreatePixmapCursor(g_dpy, bm_no, bm_no, &black, &black, 0, 0);
|
||||
|
||||
XDefineCursor(g_dpy, g_win, no_ptr);
|
||||
XFreeCursor(g_dpy, no_ptr);
|
||||
|
||||
if (bm_no != None)
|
||||
XFreePixmap(g_dpy, bm_no);
|
||||
|
||||
XFreeColors(g_dpy, colormap, &black.pixel, 1, 0);
|
||||
}
|
||||
|
||||
static Atom XA_NET_WM_STATE;
|
||||
static Atom XA_NET_WM_STATE_FULLSCREEN;
|
||||
#define XA_INIT(x) XA##x = XInternAtom(g_dpy, #x, False)
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
static void set_windowed_fullscreen(void)
|
||||
{
|
||||
XA_INIT(_NET_WM_STATE);
|
||||
XA_INIT(_NET_WM_STATE_FULLSCREEN);
|
||||
|
||||
if (!XA_NET_WM_STATE || !XA_NET_WM_STATE_FULLSCREEN)
|
||||
{
|
||||
RARCH_ERR("[X/EGL]: Cannot set windowed fullscreen.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
XEvent xev;
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.serial = 0;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.message_type = XA_NET_WM_STATE;
|
||||
xev.xclient.window = g_win;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
||||
xev.xclient.data.l[1] = XA_NET_WM_STATE_FULLSCREEN;
|
||||
xev.xclient.data.l[2] = 0;
|
||||
xev.xclient.data.l[3] = 0;
|
||||
xev.xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent(g_dpy, DefaultRootWindow(g_dpy), False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
&xev);
|
||||
}
|
||||
|
||||
void gfx_ctx_set_swap_interval(unsigned interval, bool inited)
|
||||
{
|
||||
g_interval = interval;
|
||||
if (inited)
|
||||
eglSwapInterval(g_egl_dpy, g_interval);
|
||||
}
|
||||
|
||||
void gfx_ctx_check_window(bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
|
||||
{
|
||||
(void)frame_count;
|
||||
|
||||
unsigned new_width = *width, new_height = *height;
|
||||
gfx_ctx_get_video_size(&new_width, &new_height);
|
||||
|
||||
if (new_width != *width || new_height != *height)
|
||||
{
|
||||
*resize = true;
|
||||
*width = new_width;
|
||||
*height = new_height;
|
||||
}
|
||||
|
||||
XEvent event;
|
||||
while (XPending(g_dpy))
|
||||
{
|
||||
XNextEvent(g_dpy, &event);
|
||||
switch (event.type)
|
||||
{
|
||||
case ClientMessage:
|
||||
if ((Atom)event.xclient.data.l[0] == g_quit_atom)
|
||||
g_quit = true;
|
||||
break;
|
||||
|
||||
case DestroyNotify:
|
||||
g_quit = true;
|
||||
break;
|
||||
|
||||
case MapNotify:
|
||||
g_has_focus = false;
|
||||
break;
|
||||
|
||||
case UnmapNotify:
|
||||
g_has_focus = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*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)
|
||||
{
|
||||
if (reset)
|
||||
gfx_window_title_reset();
|
||||
|
||||
char buf[128];
|
||||
if (gfx_window_title(buf, sizeof(buf)))
|
||||
XStoreName(g_dpy, g_win, buf);
|
||||
}
|
||||
|
||||
void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
|
||||
{
|
||||
if (!g_dpy || g_win == None)
|
||||
{
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
XWindowAttributes target;
|
||||
XGetWindowAttributes(g_dpy, g_win, &target);
|
||||
|
||||
*width = target.width;
|
||||
*height = target.height;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_ctx_init(void)
|
||||
{
|
||||
if (g_inited)
|
||||
return false;
|
||||
|
||||
g_quit = 0;
|
||||
|
||||
g_dpy = XOpenDisplay(NULL);
|
||||
if (!g_dpy)
|
||||
goto error;
|
||||
|
||||
g_egl_dpy = eglGetDisplay(g_dpy);
|
||||
if (!g_egl_dpy)
|
||||
goto error;
|
||||
|
||||
EGLint egl_major, egl_minor;
|
||||
if (!eglInitialize(g_egl_dpy, &egl_major, &egl_minor))
|
||||
goto error;
|
||||
|
||||
RARCH_LOG("[X/EGL]: EGL version: %d.%d\n", egl_major, egl_minor);
|
||||
|
||||
const EGLint egl_attribs[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
EGL_GREEN_SIZE, 1,
|
||||
EGL_BLUE_SIZE, 1,
|
||||
EGL_DEPTH_SIZE, 1,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
EGLint num_configs;
|
||||
if (!eglChooseConfig(g_egl_dpy, egl_attribs, &g_config, 1, &num_configs)
|
||||
|| num_configs == 0 || !g_config)
|
||||
goto error;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
gfx_ctx_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gfx_ctx_set_video_mode(
|
||||
unsigned width, unsigned height,
|
||||
unsigned bits, bool fullscreen)
|
||||
{
|
||||
(void)bits;
|
||||
const EGLint egl_ctx_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
XVisualInfo *vi = NULL;
|
||||
|
||||
EGLint vid;
|
||||
if (!eglGetConfigAttrib(g_egl_dpy, g_config, EGL_NATIVE_VISUAL_ID, &vid))
|
||||
goto error;
|
||||
|
||||
XVisualInfo template = {0};
|
||||
template.visualid = vid;
|
||||
|
||||
EGLint num_visuals;
|
||||
vi = XGetVisualInfo(g_dpy, VisualIDMask, &template, &num_visuals);
|
||||
if (!vi)
|
||||
goto error;
|
||||
|
||||
XSetWindowAttributes swa = {0};
|
||||
swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen),
|
||||
vi->visual, AllocNone);
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
|
||||
g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen),
|
||||
0, 0, width ? width : 200, height ? height : 200, 0,
|
||||
vi->depth, InputOutput, vi->visual,
|
||||
CWBorderPixel | CWColormap | CWEventMask, &swa);
|
||||
XSetWindowBackground(g_dpy, g_win, 0);
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES2_BIT);
|
||||
|
||||
g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, egl_ctx_attribs);
|
||||
if (!g_egl_ctx)
|
||||
goto error;
|
||||
|
||||
g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, g_win, NULL);
|
||||
if (!g_egl_surf)
|
||||
goto error;
|
||||
|
||||
if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
|
||||
goto error;
|
||||
|
||||
gfx_ctx_update_window_title(true);
|
||||
hide_mouse();
|
||||
XMapWindow(g_dpy, g_win);
|
||||
|
||||
if (fullscreen)
|
||||
set_windowed_fullscreen();
|
||||
|
||||
g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False);
|
||||
if (g_quit_atom)
|
||||
XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1);
|
||||
|
||||
// Catch signals.
|
||||
struct sigaction sa = {
|
||||
.sa_handler = sighandler,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
XFree(vi);
|
||||
g_has_focus = true;
|
||||
g_inited = true;
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (vi)
|
||||
XFree(vi);
|
||||
|
||||
gfx_ctx_destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
void gfx_ctx_destroy(void)
|
||||
{
|
||||
if (g_egl_dpy)
|
||||
{
|
||||
if (g_egl_ctx)
|
||||
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;
|
||||
|
||||
if (g_win)
|
||||
{
|
||||
XDestroyWindow(g_dpy, g_win);
|
||||
g_win = None;
|
||||
}
|
||||
|
||||
if (g_cmap)
|
||||
{
|
||||
XFreeColormap(g_dpy, g_cmap);
|
||||
g_cmap = None;
|
||||
}
|
||||
|
||||
if (g_dpy)
|
||||
{
|
||||
XCloseDisplay(g_dpy);
|
||||
g_dpy = NULL;
|
||||
}
|
||||
|
||||
g_inited = false;
|
||||
}
|
||||
|
||||
void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
|
||||
{
|
||||
void *xinput = input_x.init();
|
||||
*input = xinput ? &input_x : NULL;
|
||||
*input_data = xinput;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!g_inited)
|
||||
return false;
|
||||
|
||||
Window win;
|
||||
int rev;
|
||||
XGetInputFocus(g_dpy, &win, &rev);
|
||||
|
||||
return win == g_win && g_has_focus;
|
||||
}
|
||||
|
||||
// Enforce void (*)(void) as it's not really legal to cast void* to fn-pointer.
|
||||
// POSIX allows this, but strict C99 doesn't.
|
||||
gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
||||
{
|
||||
return eglGetProcAddress(symbol);
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ void gl_init_font(gl_t *gl, const char *font_path, unsigned font_size)
|
||||
{
|
||||
glGenTextures(1, &gl->font_tex);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->font_tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
|
||||
@ -127,6 +127,12 @@ static void calculate_msg_geometry(const struct font_output *head, struct font_r
|
||||
rect->height = y_max - y_min;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENGLES2
|
||||
#define INTENSITY_FORMAT GL_LUMINANCE
|
||||
#else
|
||||
#define INTENSITY_FORMAT GL_INTENSITY8
|
||||
#endif
|
||||
|
||||
static void adjust_power_of_two(gl_t *gl, struct font_rect *geom)
|
||||
{
|
||||
// Some systems really hate NPOT textures.
|
||||
@ -139,15 +145,12 @@ static void adjust_power_of_two(gl_t *gl, struct font_rect *geom)
|
||||
memset(gl->font_tex_empty_buf, 0, geom->pot_width * geom->pot_height);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, geom->pot_width);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY8, geom->pot_width, geom->pot_height,
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, INTENSITY_FORMAT, geom->pot_width, geom->pot_height,
|
||||
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
|
||||
|
||||
gl->font_tex_w = geom->pot_width;
|
||||
gl->font_tex_h = geom->pot_height;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
}
|
||||
|
||||
// Old style "blitting", so we can render all the fonts in one go.
|
||||
@ -156,7 +159,6 @@ static void blit_fonts(gl_t *gl, const struct font_output *head, const struct fo
|
||||
{
|
||||
// Clear out earlier fonts.
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0, gl->font_tex_w, gl->font_tex_h,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
|
||||
@ -168,16 +170,37 @@ static void blit_fonts(gl_t *gl, const struct font_output *head, const struct fo
|
||||
int y = head->off_y - geom->y;
|
||||
y = gl->font_tex_h - head->height - y - 1;
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(head->pitch));
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(head->width));
|
||||
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, head->pitch);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, x, y, head->width, head->height,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, head->output);
|
||||
#else
|
||||
if (head->width == head->pitch)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, x, y, head->width, head->height,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, head->output);
|
||||
}
|
||||
else // Slower path
|
||||
{
|
||||
const uint8_t *src = head->output;
|
||||
for (int i = 0; i < head->height; src += head->pitch, y++)
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, x, y, head->width, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, src);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
head = head->next;
|
||||
}
|
||||
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void calculate_font_coords(gl_t *gl,
|
||||
|
@ -49,8 +49,6 @@ void gfx_ctx_destroy(void);
|
||||
void gfx_ctx_get_video_size(unsigned *width, unsigned *height);
|
||||
void gfx_ctx_update_window_title(bool reset);
|
||||
|
||||
bool gfx_ctx_key_pressed(int key);
|
||||
|
||||
void gfx_ctx_check_window(bool *quit,
|
||||
bool *resize, unsigned *width, unsigned *height, unsigned frame_count);
|
||||
|
||||
|
110
gfx/gl.c
110
gfx/gl.c
@ -44,23 +44,6 @@
|
||||
#include "shader_glsl.h"
|
||||
#endif
|
||||
|
||||
// Platform specific workarounds/hacks.
|
||||
#if defined(__CELLOS_LV2__) || defined(HAVE_OPENGLES)
|
||||
#define NO_GL_READ_VIEWPORT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL_MODERN) || defined(HAVE_OPENGLES2)
|
||||
#define NO_GL_FF_VERTEX
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL_MODERN) || defined(HAVE_OPENGLES2) || defined(HAVE_PSGL)
|
||||
#define NO_GL_FF_MATRIX
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) // TODO: Figure out exactly what.
|
||||
#define NO_GL_CLAMP_TO_BORDER
|
||||
#endif
|
||||
|
||||
// Used for the last pass when rendering to the back buffer.
|
||||
const GLfloat vertexes_flipped[] = {
|
||||
0, 1,
|
||||
@ -127,6 +110,13 @@ static bool load_fbo_proc(void)
|
||||
return pglGenFramebuffers && pglBindFramebuffer && pglFramebufferTexture2D &&
|
||||
pglCheckFramebufferStatus && pglDeleteFramebuffers;
|
||||
}
|
||||
#elif defined(HAVE_OPENGLES2)
|
||||
#define pglGenFramebuffers glGenFramebuffers
|
||||
#define pglBindFramebuffer glBindFramebuffer
|
||||
#define pglFramebufferTexture2D glFramebufferTexture2D
|
||||
#define pglCheckFramebufferStatus glCheckFramebufferStatus
|
||||
#define pglDeleteFramebuffers glDeleteFramebuffers
|
||||
static bool load_fbo_proc(void) { return true; }
|
||||
#elif defined(HAVE_OPENGLES)
|
||||
#define pglGenFramebuffers glGenFramebuffersOES
|
||||
#define pglBindFramebuffer glBindFramebufferOES
|
||||
@ -136,7 +126,6 @@ static bool load_fbo_proc(void)
|
||||
#define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
|
||||
#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
|
||||
#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
|
||||
#define glOrtho glOrthof
|
||||
static bool load_fbo_proc(void) { return true; }
|
||||
#else
|
||||
#define pglGenFramebuffers glGenFramebuffers
|
||||
@ -830,9 +819,6 @@ static void gl_update_input_size(gl_t *gl, unsigned width, unsigned height, unsi
|
||||
#else
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * gl->base_size));
|
||||
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
#endif
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0, gl->tex_w, gl->tex_h, gl->texture_type,
|
||||
gl->texture_fmt, gl->empty_buf);
|
||||
@ -949,6 +935,40 @@ static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, un
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(width * gl->base_size));
|
||||
|
||||
#ifdef HAVE_OPENGLES2 // Have to perform pixel format conversions as well. (ARGB1555 => RGBA5551), (ARGB8888 => RGBA8888) :(
|
||||
if (gl->base_size == 4) // ARGB8888 => RGBA8888
|
||||
{
|
||||
const uint32_t *src = (const uint32_t*)frame;
|
||||
uint32_t *dst = (uint32_t*)gl->conv_buffer;
|
||||
unsigned pitch_width = pitch >> 2;
|
||||
|
||||
// GL_RGBA + GL_UNSIGNED_BYTE apparently means in byte order, so go with little endian for now (ABGR).
|
||||
for (unsigned h = 0; h < height; h++, dst += width, src += pitch_width)
|
||||
{
|
||||
for (unsigned w = 0; w < width; w++)
|
||||
{
|
||||
uint32_t col = src[w];
|
||||
dst[w] = ((col << 16) & 0x00ff0000) | ((col >> 16) & 0x000000ff) | (col & 0xff00ff00);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // ARGB1555 => RGBA1555
|
||||
{
|
||||
// Go 32-bit at once.
|
||||
unsigned half_width = width >> 1;
|
||||
const uint32_t *src = (const uint32_t*)frame;
|
||||
uint32_t *dst = (uint32_t*)gl->conv_buffer;
|
||||
unsigned pitch_width = pitch >> 2;
|
||||
|
||||
for (unsigned h = 0; h < height; h++, dst += half_width, src += pitch_width)
|
||||
for (unsigned w = 0; w < half_width; w++)
|
||||
dst[w] = (src[w] << 1) & 0xfffefffe;
|
||||
}
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0, width, height, gl->texture_type,
|
||||
gl->texture_fmt, gl->conv_buffer);
|
||||
#else
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / gl->base_size);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
@ -974,6 +994,7 @@ static inline void gl_copy_frame(gl_t *gl, const void *frame, unsigned width, un
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gl_init_textures(gl_t *gl)
|
||||
@ -988,10 +1009,6 @@ static void gl_init_textures(gl_t *gl)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl->tex_filter);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl->tex_filter);
|
||||
|
||||
#ifdef GL_UNPACK_ROW_LENGTH
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, RARCH_GL_INTERNAL_FORMAT, gl->tex_w, gl->tex_h, 0, gl->texture_type,
|
||||
gl->texture_fmt, gl->empty_buf ? gl->empty_buf : NULL);
|
||||
@ -1152,8 +1169,8 @@ static void gl_free(void *data)
|
||||
|
||||
gfx_ctx_destroy();
|
||||
|
||||
if (gl->empty_buf)
|
||||
free(gl->empty_buf);
|
||||
free(gl->empty_buf);
|
||||
free(gl->conv_buffer);
|
||||
|
||||
free(gl);
|
||||
}
|
||||
@ -1176,18 +1193,16 @@ static bool resolve_extensions(gl_t *gl)
|
||||
#endif
|
||||
|
||||
#ifdef NO_GL_CLAMP_TO_BORDER
|
||||
// Doesn't support GL_CLAMP_TO_BORDER. NOTE: This will be a serious problem for some shaders.
|
||||
//
|
||||
// NOTE2: We still need to query if GL_CLAMP_TO_BORDER is supported even if compiling with
|
||||
// OpenGL ES 1 because none of these defines are in any system headers except for what every
|
||||
// Android GPU supports (which doesn't include GL_CLAMP_TO_BORDER) - move the underlying value
|
||||
// for GL_CLAMP_TO_BORDER to some variable that we'll use here and query at gl_init if
|
||||
// GL_CLAMP_TO_BORDER is available
|
||||
// NOTE: This will be a serious problem for some shaders.
|
||||
gl->border_type = GL_CLAMP_TO_EDGE;
|
||||
#else
|
||||
gl->border_type = GL_CLAMP_TO_BORDER;
|
||||
#endif
|
||||
|
||||
const char *ext = (const char*)glGetString(GL_EXTENSIONS);
|
||||
if (ext)
|
||||
RARCH_LOG("[GL] Supported extensions: %s\n", ext);
|
||||
|
||||
#if defined(HAVE_PBO)
|
||||
RARCH_LOG("[GL]: Using PBOs.\n");
|
||||
if (!gl_query_extension("GL_ARB_pixel_buffer_object"))
|
||||
@ -1197,10 +1212,6 @@ static bool resolve_extensions(gl_t *gl)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GL_UNPACK_ROW_LENGTH
|
||||
RARCH_WARN("[GL]: GL_UNPACK_ROW_LENGTH is not defined. Texture uploads will possibly be slower than optimal.\n");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1289,7 +1300,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl_init_fbo(gl, RARCH_SCALE_BASE * video->input_scale,
|
||||
RARCH_SCALE_BASE * video->input_scale);
|
||||
#endif
|
||||
|
||||
|
||||
gl->keep_aspect = video->force_aspect;
|
||||
|
||||
// Apparently need to set viewport for passes when we aren't using FBOs.
|
||||
@ -1308,7 +1319,10 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl->texture_fmt = video->rgb32 ? RARCH_GL_FORMAT32 : RARCH_GL_FORMAT16;
|
||||
gl->base_size = video->rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||
|
||||
#ifndef HAVE_OPENGLES
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
#endif
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_DITHER);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
@ -1337,6 +1351,17 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
|
||||
// Empty buffer that we use to clear out the texture with on res change.
|
||||
gl->empty_buf = calloc(gl->tex_w * gl->tex_h, gl->base_size);
|
||||
|
||||
#ifdef HAVE_OPENGLES2
|
||||
gl->conv_buffer = calloc(gl->tex_w * gl->tex_h, gl->base_size);
|
||||
if (!gl->conv_buffer)
|
||||
{
|
||||
gfx_ctx_destroy();
|
||||
free(gl);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
gl_init_textures(gl);
|
||||
|
||||
for (unsigned i = 0; i < TEXTURES; i++)
|
||||
@ -1347,18 +1372,17 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
|
||||
for (unsigned i = 0; i < TEXTURES; i++)
|
||||
{
|
||||
gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK];
|
||||
gl->prev_info[i].tex = gl->texture[(gl->tex_index - (i + 1)) & TEXTURES_MASK];
|
||||
gl->prev_info[i].input_size[0] = gl->tex_w;
|
||||
gl->prev_info[i].tex_size[0] = gl->tex_w;
|
||||
gl->prev_info[i].tex_size[0] = gl->tex_w;
|
||||
gl->prev_info[i].input_size[1] = gl->tex_h;
|
||||
gl->prev_info[i].tex_size[1] = gl->tex_h;
|
||||
gl->prev_info[i].tex_size[1] = gl->tex_h;
|
||||
memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords));
|
||||
}
|
||||
|
||||
gfx_ctx_input_driver(input, input_data);
|
||||
gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size);
|
||||
|
||||
|
||||
if (!gl_check_error())
|
||||
{
|
||||
gfx_ctx_destroy();
|
||||
|
@ -176,6 +176,7 @@ typedef struct gl
|
||||
GLuint tex_filter;
|
||||
|
||||
void *empty_buf;
|
||||
void *conv_buffer;
|
||||
|
||||
unsigned frame_count;
|
||||
|
||||
@ -245,8 +246,8 @@ extern PFNGLACTIVETEXTUREPROC pglActiveTexture;
|
||||
#elif defined(HAVE_OPENGLES)
|
||||
#define RARCH_GL_INTERNAL_FORMAT GL_RGBA
|
||||
#define RARCH_GL_TEXTURE_TYPE GL_RGBA
|
||||
#define RARCH_GL_FORMAT32 GL_UNSIGNED_INT
|
||||
#define RARCH_GL_FORMAT16 GL_UNSIGNED_SHORT
|
||||
#define RARCH_GL_FORMAT32 GL_UNSIGNED_BYTE
|
||||
#define RARCH_GL_FORMAT16 GL_UNSIGNED_SHORT_5_5_5_1
|
||||
#else
|
||||
#define RARCH_GL_INTERNAL_FORMAT GL_RGBA
|
||||
#define RARCH_GL_TEXTURE_TYPE GL_BGRA
|
||||
@ -254,6 +255,27 @@ extern PFNGLACTIVETEXTUREPROC pglActiveTexture;
|
||||
#define RARCH_GL_FORMAT16 GL_UNSIGNED_SHORT_1_5_5_5_REV
|
||||
#endif
|
||||
|
||||
// Platform specific workarounds/hacks.
|
||||
#if defined(__CELLOS_LV2__) || defined(HAVE_OPENGLES)
|
||||
#define NO_GL_READ_VIEWPORT
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL_MODERN) || defined(HAVE_OPENGLES2)
|
||||
#define NO_GL_FF_VERTEX
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL_MODERN) || defined(HAVE_OPENGLES2) || defined(HAVE_PSGL)
|
||||
#define NO_GL_FF_MATRIX
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGLES2) // TODO: Figure out exactly what.
|
||||
#define NO_GL_CLAMP_TO_BORDER
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGLES2) // It's an extension. Don't bother checking for it atm.
|
||||
#undef GL_UNPACK_ROW_LENGTH
|
||||
#endif
|
||||
|
||||
void gl_shader_use(unsigned index);
|
||||
void gl_set_projection(gl_t *gl, struct gl_ortho *ortho, bool allow_rotate);
|
||||
void gl_set_viewport(gl_t *gl, unsigned width, unsigned height, bool force_full, bool allow_rotate);
|
||||
|
@ -292,7 +292,8 @@ static void *sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
|
||||
#ifdef HAVE_X11
|
||||
RARCH_LOG("Suspending screensaver (X11).\n");
|
||||
SDL_SysWMinfo wm_info;
|
||||
if (gfx_ctx_get_wm_info(&wm_info))
|
||||
SDL_VERSION(&wm_info.version);
|
||||
if (SDL_GetWMInfo(&wm_info) == 1)
|
||||
gfx_suspend_screensaver(wm_info.info.x11.window);
|
||||
else
|
||||
RARCH_ERR("Failed to suspend screensaver.\n");
|
||||
|
@ -60,6 +60,33 @@
|
||||
#include "gl_common.h"
|
||||
#include "image.h"
|
||||
|
||||
#if defined(HAVE_OPENGLES2) || defined(HAVE_OPENGL_MODERN)
|
||||
#define pglCreateProgram glCreateProgram
|
||||
#define pglUseProgram glUseProgram
|
||||
#define pglCreateShader glCreateShader
|
||||
#define pglDeleteShader glDeleteShader
|
||||
#define pglShaderSource glShaderSource
|
||||
#define pglCompileShader glCompileShader
|
||||
#define pglAttachShader glAttachShader
|
||||
#define pglDetachShader glDetachShader
|
||||
#define pglLinkProgram glLinkProgram
|
||||
#define pglGetUniformLocation glGetUniformLocation
|
||||
#define pglUniform1i glUniform1i
|
||||
#define pglUniform1f glUniform1f
|
||||
#define pglUniform2fv glUniform2fv
|
||||
#define pglUniform4fv glUniform4fv
|
||||
#define pglUniformMatrix4fv glUniformMatrix4fv
|
||||
#define pglGetShaderiv glGetShaderiv
|
||||
#define pglGetShaderInfoLog glGetShaderInfoLog
|
||||
#define pglGetProgramiv glGetProgramiv
|
||||
#define pglGetProgramInfoLog glGetProgramInfoLog
|
||||
#define pglDeleteProgram glDeleteProgram
|
||||
#define pglGetAttachedShaders glGetAttachedShaders
|
||||
#define pglGetAttribLocation glGetAttribLocation
|
||||
#define pglEnableVertexAttribArray glEnableVertexAttribArray
|
||||
#define pglDisableVertexAttribArray glDisableVertexAttribArray
|
||||
#define pglVertexAttribPointer glVertexAttribPointer
|
||||
#else
|
||||
static PFNGLCREATEPROGRAMPROC pglCreateProgram = NULL;
|
||||
static PFNGLUSEPROGRAMPROC pglUseProgram = NULL;
|
||||
static PFNGLCREATESHADERPROC pglCreateShader = NULL;
|
||||
@ -85,6 +112,13 @@ static PFNGLGETATTRIBLOCATIONPROC pglGetAttribLocation = NULL;
|
||||
static PFNGLENABLEVERTEXATTRIBARRAYPROC pglEnableVertexAttribArray = NULL;
|
||||
static PFNGLDISABLEVERTEXATTRIBARRAYPROC pglDisableVertexAttribArray = NULL;
|
||||
static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENGLES2
|
||||
#define BORDER_FUNC GL_CLAMP_TO_EDGE
|
||||
#else
|
||||
#define BORDER_FUNC GL_CLAMP_TO_BORDER
|
||||
#endif
|
||||
|
||||
#define MAX_PROGRAMS 16
|
||||
#define MAX_TEXTURES 8
|
||||
@ -390,15 +424,17 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr)
|
||||
|
||||
pglActiveTexture(GL_TEXTURE0 + gl_teximage_cnt + 1);
|
||||
glBindTexture(GL_TEXTURE_2D, gl_teximage[gl_teximage_cnt]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, BORDER_FUNC);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, BORDER_FUNC);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linear ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_RGBA, img.width, img.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, img.pixels);
|
||||
0, RARCH_GL_INTERNAL_FORMAT,
|
||||
img.width, img.height, 0, RARCH_GL_TEXTURE_TYPE, GL_UNSIGNED_INT, img.pixels);
|
||||
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
@ -893,17 +929,14 @@ static void gl_glsl_reset_attrib(void)
|
||||
|
||||
// Platforms with broken get_proc_address.
|
||||
// Assume functions are available without proc_address.
|
||||
#ifdef __PSL1GHT__
|
||||
#define LOAD_GL_SYM(SYM) pgl##SYM = gl##SYM;
|
||||
#else
|
||||
#define LOAD_GL_SYM(SYM) if (!pgl##SYM) { \
|
||||
gfx_ctx_proc_t sym = gfx_ctx_get_proc_address("gl" #SYM); \
|
||||
memcpy(&(pgl##SYM), &sym, sizeof(sym)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
bool gl_glsl_init(const char *path)
|
||||
{
|
||||
#if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN)
|
||||
// Load shader functions.
|
||||
LOAD_GL_SYM(CreateProgram);
|
||||
LOAD_GL_SYM(UseProgram);
|
||||
@ -946,6 +979,7 @@ bool gl_glsl_init(const char *path)
|
||||
RARCH_ERR("GLSL shaders aren't supported by your OpenGL driver.\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XML
|
||||
struct shader_program progs[MAX_PROGRAMS];
|
||||
|
@ -182,7 +182,15 @@ static void *sdl_input_init(void)
|
||||
|
||||
static bool sdl_key_pressed(int key)
|
||||
{
|
||||
return key < RETROK_LAST && gfx_ctx_key_pressed(keysym_lut[key]);
|
||||
if (key >= RETROK_LAST)
|
||||
return false;
|
||||
|
||||
int num_keys;
|
||||
Uint8 *keymap = SDL_GetKeyState(&num_keys);
|
||||
if (key >= num_keys)
|
||||
return false;
|
||||
|
||||
return keymap[key];
|
||||
}
|
||||
|
||||
#ifndef HAVE_DINPUT
|
||||
|
@ -145,6 +145,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 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 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"
|
||||
create_config_make config.mk $VARS
|
||||
create_config_header config.h $VARS
|
||||
|
@ -6,6 +6,7 @@ HAVE_DYLIB=auto # Enable dynamic loading support
|
||||
HAVE_NETPLAY=auto # Enable netplay support
|
||||
HAVE_CONFIGFILE=yes # Disable support for config file
|
||||
HAVE_OPENGL=yes # Disable OpenGL support
|
||||
HAVE_GLES=no # Use X/EGL instead of desktop GL (experimental)
|
||||
HAVE_CG=auto # Enable Cg shader support
|
||||
HAVE_XML=auto # Enable bSNES-style XML shader support
|
||||
HAVE_FBO=auto # Enable render-to-texture (FBO) support
|
||||
|
Loading…
x
Reference in New Issue
Block a user