mirror of
https://github.com/libretro/RetroArch
synced 2025-02-16 03:40:12 +00:00
(Android) Use EGL context file
This commit is contained in:
parent
d30d345d84
commit
8ac8b16d34
@ -1,9 +1,6 @@
|
|||||||
#ifndef _ANDROID_GENERAL_H
|
#ifndef _ANDROID_GENERAL_H
|
||||||
#define _ANDROID_GENERAL_H
|
#define _ANDROID_GENERAL_H
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
|
||||||
#include <GLES/gl.h>
|
|
||||||
|
|
||||||
#include <android/sensor.h>
|
#include <android/sensor.h>
|
||||||
#include <android_native_app_glue.h>
|
#include <android_native_app_glue.h>
|
||||||
|
|
||||||
@ -22,12 +19,9 @@ struct droid
|
|||||||
const ASensor* accelerometerSensor;
|
const ASensor* accelerometerSensor;
|
||||||
ASensorEventQueue* sensorEventQueue;
|
ASensorEventQueue* sensorEventQueue;
|
||||||
|
|
||||||
int animating;
|
unsigned animating;
|
||||||
EGLDisplay display;
|
unsigned width;
|
||||||
EGLSurface surface;
|
unsigned height;
|
||||||
EGLContext context;
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
struct saved_state state;
|
struct saved_state state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,9 +18,18 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <EGL/egl.h> /* Requires NDK r5 or newer */
|
||||||
|
#include <GLES/gl.h>
|
||||||
|
|
||||||
#include "android-general.h"
|
#include "android-general.h"
|
||||||
#include "../../../general.h"
|
#include "../../../general.h"
|
||||||
|
|
||||||
|
//forward declarations
|
||||||
|
void gfx_ctx_swap_buffers(void);
|
||||||
|
void gfx_ctx_clear(void);
|
||||||
|
void gfx_ctx_destroy(void);
|
||||||
|
bool gfx_ctx_init(void);
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt)
|
JNIEXPORT jint JNICALL JNI_OnLoad( JavaVM *vm, void *pvt)
|
||||||
{
|
{
|
||||||
RARCH_LOG("JNI_OnLoad.\n" );
|
RARCH_LOG("JNI_OnLoad.\n" );
|
||||||
@ -33,108 +42,17 @@ JNIEXPORT void JNICALL JNI_OnUnLoad( JavaVM *vm, void *pvt)
|
|||||||
RARCH_LOG("JNI_OnUnLoad.\n" );
|
RARCH_LOG("JNI_OnUnLoad.\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize an EGL context for the current display.
|
|
||||||
*/
|
|
||||||
static int engine_init_display(void)
|
|
||||||
{
|
|
||||||
// initialize OpenGL ES and EGL
|
|
||||||
|
|
||||||
const EGLint attribs[] =
|
|
||||||
{
|
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
||||||
EGL_BLUE_SIZE, 8,
|
|
||||||
EGL_GREEN_SIZE, 8,
|
|
||||||
EGL_RED_SIZE, 8,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
EGLint w, h, dummy, format;
|
|
||||||
EGLint numConfigs;
|
|
||||||
EGLConfig config;
|
|
||||||
EGLSurface surface;
|
|
||||||
EGLContext context;
|
|
||||||
|
|
||||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
||||||
|
|
||||||
eglInitialize(display, 0, 0);
|
|
||||||
|
|
||||||
/* Here, the application chooses the configuration it desires. In this
|
|
||||||
* sample, we have a very simplified selection process, where we pick
|
|
||||||
* the first EGLConfig that matches our criteria */
|
|
||||||
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
|
|
||||||
|
|
||||||
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
|
|
||||||
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
|
|
||||||
* As soon as we picked a EGLConfig, we can safely reconfigure the
|
|
||||||
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
|
|
||||||
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
|
|
||||||
|
|
||||||
ANativeWindow_setBuffersGeometry(g_android.app->window, 0, 0, format);
|
|
||||||
|
|
||||||
surface = eglCreateWindowSurface(display, config, g_android.app->window, NULL);
|
|
||||||
context = eglCreateContext(display, config, NULL, NULL);
|
|
||||||
|
|
||||||
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
|
|
||||||
{
|
|
||||||
RARCH_ERR("Unable to eglMakeCurrent.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglQuerySurface(display, surface, EGL_WIDTH, &w);
|
|
||||||
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
|
|
||||||
|
|
||||||
g_android.display = display;
|
|
||||||
g_android.context = context;
|
|
||||||
g_android.surface = surface;
|
|
||||||
g_android.width = w;
|
|
||||||
g_android.height = h;
|
|
||||||
g_android.state.angle = 0;
|
|
||||||
|
|
||||||
// Initialize GL state.
|
|
||||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just the current frame in the display.
|
* Just the current frame in the display.
|
||||||
*/
|
*/
|
||||||
static void engine_draw_frame(void)
|
static void engine_draw_frame(void)
|
||||||
{
|
{
|
||||||
if (g_android.display == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Just fill the screen with a color.
|
// Just fill the screen with a color.
|
||||||
glClearColor(((float)g_android.state.x)/g_android.width, g_android.state.angle,
|
glClearColor(((float)g_android.state.x)/g_android.width, g_android.state.angle,
|
||||||
((float)g_android.state.y)/g_android.height, 1);
|
((float)g_android.state.y)/g_android.height, 1);
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
gfx_ctx_clear();
|
||||||
|
gfx_ctx_swap_buffers();
|
||||||
eglSwapBuffers(g_android.display, g_android.surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tear down the EGL context currently associated with the display.
|
|
||||||
*/
|
|
||||||
static void engine_term_display(void)
|
|
||||||
{
|
|
||||||
if (g_android.display != EGL_NO_DISPLAY)
|
|
||||||
{
|
|
||||||
eglMakeCurrent(g_android.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
||||||
|
|
||||||
if (g_android.context != EGL_NO_CONTEXT)
|
|
||||||
eglDestroyContext(g_android.display, g_android.context);
|
|
||||||
if (g_android.surface != EGL_NO_SURFACE)
|
|
||||||
eglDestroySurface(g_android.display, g_android.surface);
|
|
||||||
|
|
||||||
eglTerminate(g_android.display);
|
|
||||||
}
|
|
||||||
g_android.animating = 0;
|
|
||||||
g_android.display = EGL_NO_DISPLAY;
|
|
||||||
g_android.context = EGL_NO_CONTEXT;
|
|
||||||
g_android.surface = EGL_NO_SURFACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,13 +87,13 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd)
|
|||||||
// The window is being shown, get it ready.
|
// The window is being shown, get it ready.
|
||||||
if (g_android.app->window != NULL)
|
if (g_android.app->window != NULL)
|
||||||
{
|
{
|
||||||
engine_init_display();
|
gfx_ctx_init();
|
||||||
engine_draw_frame();
|
engine_draw_frame();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
// The window is being hidden or closed, clean it up.
|
// The window is being hidden or closed, clean it up.
|
||||||
engine_term_display();
|
gfx_ctx_destroy();
|
||||||
break;
|
break;
|
||||||
case APP_CMD_GAINED_FOCUS:
|
case APP_CMD_GAINED_FOCUS:
|
||||||
// When our app gains focus, we start monitoring the accelerometer.
|
// When our app gains focus, we start monitoring the accelerometer.
|
||||||
@ -260,7 +178,7 @@ void android_main(struct android_app* state)
|
|||||||
// Check if we are exiting.
|
// Check if we are exiting.
|
||||||
if (state->destroyRequested != 0)
|
if (state->destroyRequested != 0)
|
||||||
{
|
{
|
||||||
engine_term_display();
|
gfx_ctx_destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <EGL/egl.h> /* Requires NDK r5 or newer */
|
#include <EGL/egl.h> /* Requires NDK r5 or newer */
|
||||||
#include <GLES/gl.h>
|
#include <GLES/gl.h>
|
||||||
|
|
||||||
|
#include "../../android/native/jni/android-general.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum RenderThreadMessage {
|
enum RenderThreadMessage {
|
||||||
@ -28,17 +30,11 @@ enum RenderThreadMessage {
|
|||||||
MSG_RENDER_LOOP_EXIT
|
MSG_RENDER_LOOP_EXIT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RenderThreadMessage _msg;
|
|
||||||
|
|
||||||
ANativeWindow *window; /* Requires NDK r5 or newer */
|
|
||||||
|
|
||||||
static EGLContext g_egl_ctx;
|
static EGLContext g_egl_ctx;
|
||||||
static EGLSurface g_egl_surf;
|
static EGLSurface g_egl_surf;
|
||||||
static EGLDisplay g_egl_dpy;
|
static EGLDisplay g_egl_dpy;
|
||||||
static EGLConfig g_config;
|
static EGLConfig g_config;
|
||||||
|
|
||||||
int _width;
|
|
||||||
int _height;
|
|
||||||
GLfloat _angle;
|
GLfloat _angle;
|
||||||
|
|
||||||
static enum gfx_ctx_api g_api;
|
static enum gfx_ctx_api g_api;
|
||||||
@ -74,7 +70,7 @@ static void gfx_ctx_set_swap_interval(unsigned interval)
|
|||||||
eglSwapInterval(g_egl_dpy, interval);
|
eglSwapInterval(g_egl_dpy, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_ctx_destroy(void)
|
void gfx_ctx_destroy(void)
|
||||||
{
|
{
|
||||||
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
eglDestroyContext(g_egl_dpy, g_egl_ctx);
|
eglDestroyContext(g_egl_dpy, g_egl_ctx);
|
||||||
@ -86,11 +82,12 @@ static void gfx_ctx_destroy(void)
|
|||||||
g_egl_ctx = EGL_NO_CONTEXT;
|
g_egl_ctx = EGL_NO_CONTEXT;
|
||||||
g_config = 0;
|
g_config = 0;
|
||||||
|
|
||||||
_width = 0;
|
g_android.width = 0;
|
||||||
_height = 0;
|
g_android.height = 0;
|
||||||
|
g_android.animating = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool gfx_ctx_init(void)
|
bool gfx_ctx_init(void)
|
||||||
{
|
{
|
||||||
const EGLint attribs[] = {
|
const EGLint attribs[] = {
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
@ -134,9 +131,9 @@ static bool gfx_ctx_init(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ANativeWindow_setBuffersGeometry(window, 0, 0, format);
|
ANativeWindow_setBuffersGeometry(g_android.app->window, 0, 0, format);
|
||||||
|
|
||||||
if (!(g_egl_surf = eglCreateWindowSurface(g_egl_dpy, config, window, 0))) {
|
if (!(g_egl_surf = eglCreateWindowSurface(g_egl_dpy, config, g_android.app->window, 0))) {
|
||||||
RARCH_ERR("eglCreateWindowSurface() returned error %d.\n", eglGetError());
|
RARCH_ERR("eglCreateWindowSurface() returned error %d.\n", eglGetError());
|
||||||
gfx_ctx_destroy();
|
gfx_ctx_destroy();
|
||||||
return false;
|
return false;
|
||||||
@ -161,24 +158,14 @@ static bool gfx_ctx_init(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_width = width;
|
g_android.width = width;
|
||||||
_height = height;
|
g_android.height = height;
|
||||||
|
g_android.state.angle = 0;
|
||||||
|
|
||||||
/*
|
// Initialize GL state.
|
||||||
glDisable(GL_DITHER);
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
glEnable(GL_CULL_FACE);
|
||||||
glClearColor(0, 0, 0, 0);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
glShadeModel(GL_SMOOTH);
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
glViewport(0, 0, width, height);
|
|
||||||
|
|
||||||
ratio = (GLfloat) width / height;
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glFrustumf(-ratio, ratio, -1, 1, 1, 10);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -191,33 +178,28 @@ void gfx_ctx_check_window(bool *quit,
|
|||||||
(void)width;
|
(void)width;
|
||||||
(void)height;
|
(void)height;
|
||||||
(void)frame_count;
|
(void)frame_count;
|
||||||
|
|
||||||
// process incoming messages
|
|
||||||
switch (_msg)
|
|
||||||
{
|
|
||||||
case MSG_WINDOW_SET:
|
|
||||||
gfx_ctx_init();
|
|
||||||
break;
|
|
||||||
case MSG_RENDER_LOOP_EXIT:
|
|
||||||
*quit = false;
|
|
||||||
gfx_ctx_destroy();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_msg = MSG_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_ctx_swap_buffers(void)
|
void gfx_ctx_swap_buffers(void)
|
||||||
{
|
{
|
||||||
eglSwapBuffers(g_egl_dpy, g_egl_surf);
|
eglSwapBuffers(g_egl_dpy, g_egl_surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gfx_ctx_clear(void)
|
void gfx_ctx_clear(void)
|
||||||
{}
|
{
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
static void gfx_ctx_set_blend(bool enable)
|
static void gfx_ctx_set_blend(bool enable)
|
||||||
{}
|
{
|
||||||
|
if(enable)
|
||||||
|
{
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
static void gfx_ctx_set_resize(unsigned width, unsigned height)
|
static void gfx_ctx_set_resize(unsigned width, unsigned height)
|
||||||
{
|
{
|
||||||
@ -283,9 +265,6 @@ static void gfx_ctx_set_aspect_ratio(void *data, unsigned aspectratio_index)
|
|||||||
static void gfx_ctx_set_overscan(void)
|
static void gfx_ctx_set_overscan(void)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Enforce void (*)(void) as it's not really legal to cast void* to fn-pointer.
|
|
||||||
// POSIX allows this, but strict C99 doesn't.
|
|
||||||
#ifndef __PSL1GHT__
|
|
||||||
static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
||||||
{
|
{
|
||||||
rarch_assert(sizeof(void*) == sizeof(void (*)(void)));
|
rarch_assert(sizeof(void*) == sizeof(void (*)(void)));
|
||||||
@ -296,7 +275,6 @@ static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
static bool gfx_ctx_bind_api(enum gfx_ctx_api api)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user