1
0
Fork 0
mirror of https://github.com/bjornbytes/lovr.git synced 2024-07-02 12:33:52 +00:00
lovr/src/core/os_android.c

235 lines
5.3 KiB
C
Raw Normal View History

2019-12-14 03:58:22 +00:00
#include "os.h"
#include <stdio.h>
2020-05-29 22:27:49 +00:00
#include <string.h>
#include <time.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
2020-05-29 22:27:49 +00:00
#include <android_native_app_glue.h>
#include <android/log.h>
2020-05-29 22:27:49 +00:00
#ifndef LOVR_USE_OCULUS_MOBILE
2020-01-29 05:42:44 +00:00
static struct {
EGLDisplay display;
EGLContext context;
EGLSurface surface;
} state;
static JavaVM* lovrJavaVM;
static JNIEnv* lovrJNIEnv;
int main(int argc, char** argv);
static void onAppCmd(struct android_app* app, int32_t cmd) {
// pause, resume, events, etc.
}
void android_main(struct android_app* app) {
lovrJavaVM = app->activity->vm;
2020-05-29 22:27:49 +00:00
(*lovrJavaVM)->AttachCurrentThread(lovrJavaVM, &lovrJNIEnv, NULL);
app->onAppCmd = onAppCmd;
main(0, NULL);
2020-05-29 22:27:49 +00:00
(*lovrJavaVM)->DetachCurrentThread(lovrJavaVM);
}
#endif
bool lovrPlatformInit() {
return true;
}
void lovrPlatformDestroy() {
2020-05-29 22:27:49 +00:00
#ifndef LOVR_USE_OCULUS_MOBILE
2020-01-29 05:42:44 +00:00
if (state.display) eglMakeCurrent(state.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (state.surface) eglDestroySurface(state.display, state.surface);
if (state.context) eglDestroyContext(state.display, state.context);
if (state.display) eglTerminate(state.display);
memset(&state, 0, sizeof(state));
#endif
}
const char* lovrPlatformGetName() {
return "Android";
}
2020-05-29 22:27:49 +00:00
// lovr-oculus-mobile provides its own implementation of the timing functions
#ifndef LOVR_USE_OCULUS_MOBILE
static uint64_t epoch;
#define NS_PER_SEC 1000000000ULL
static uint64_t getTime() {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return (uint64_t) t.tv_sec * NS_PER_SEC + (uint64_t) t.tv_nsec;
}
double lovrPlatformGetTime() {
return (getTime() - epoch) / (double) NS_PER_SEC;
}
void lovrPlatformSetTime(double time) {
epoch = getTime() - (uint64_t) (time * NS_PER_SEC + .5);
}
void lovrPlatformSleep(double seconds) {
seconds += .5e-9;
struct timespec t;
t.tv_sec = seconds;
t.tv_nsec = (seconds - t.tv_sec) * NS_PER_SEC;
while (nanosleep(&t, &t));
}
#endif
void lovrPlatformPollEvents() {
// TODO
}
2019-06-17 01:55:21 +00:00
void lovrPlatformOpenConsole() {
// TODO
2019-06-17 01:55:21 +00:00
}
bool lovrPlatformCreateWindow(WindowFlags* flags) {
2020-05-29 22:27:49 +00:00
#ifndef LOVR_USE_OCULUS_MOBILE // lovr-oculus-mobile creates its own EGL context
2020-01-29 05:42:44 +00:00
if (state.display) {
return true;
}
if ((state.display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
return false;
}
if (eglInitialize(state.display, NULL, NULL) == EGL_FALSE) {
return false;
}
EGLConfig configs[1024];
EGLint configCount;
if (eglGetConfigs(state.display, configs, sizeof(configs) / sizeof(configs[0]), &configCount) == EGL_FALSE) {
return false;
}
const EGLint attributes[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_SAMPLES, 0,
EGL_NONE
};
2020-02-05 00:48:03 +00:00
EGLConfig config = 0;
2020-01-29 05:42:44 +00:00
for (EGLint i = 0; i < configCount && !config; i++) {
EGLint value, mask;
mask = EGL_OPENGL_ES3_BIT_KHR;
if (!eglGetConfigAttrib(state.display, configs[i], EGL_RENDERABLE_TYPE, &value) || (value & mask) != mask) {
continue;
}
mask = EGL_PBUFFER_BIT | EGL_WINDOW_BIT;
if (!eglGetConfigAttrib(state.display, configs[i], EGL_SURFACE_TYPE, &value) || (value & mask) != mask) {
continue;
}
2020-05-29 22:27:49 +00:00
for (size_t a = 0; a < sizeof(attributes) / sizeof(attributes[0]); a += 2) {
2020-01-29 05:42:44 +00:00
if (attributes[a] == EGL_NONE) {
config = configs[i];
break;
}
if (!eglGetConfigAttrib(state.display, configs[i], attributes[a], &value) || value != attributes[a + 1]) {
break;
}
}
}
EGLint contextAttributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
2020-02-05 00:48:03 +00:00
if ((state.context = eglCreateContext(state.display, config, EGL_NO_CONTEXT, contextAttributes)) == EGL_NO_CONTEXT) {
2020-01-29 05:42:44 +00:00
return false;
}
EGLint surfaceAttributes[] = {
EGL_WIDTH, 16,
EGL_HEIGHT, 16,
EGL_NONE
};
if ((state.surface = eglCreatePbufferSurface(state.display, config, surfaceAttributes)) == EGL_NO_SURFACE) {
2020-02-05 00:48:03 +00:00
eglDestroyContext(state.display, state.context);
2020-01-29 05:42:44 +00:00
return false;
}
if (eglMakeCurrent(state.display, state.surface, state.surface, state.context) == EGL_FALSE) {
2020-02-05 00:48:03 +00:00
eglDestroySurface(state.display, state.surface);
eglDestroyContext(state.display, state.context);
2020-01-29 05:42:44 +00:00
}
#endif
return true;
}
2020-05-29 22:27:49 +00:00
#ifndef LOVR_USE_OCULUS_MOBILE
bool lovrPlatformHasWindow() {
return false;
}
#endif
void lovrPlatformGetWindowSize(int* width, int* height) {
if (width) *width = 0;
if (height) *height = 0;
}
2020-05-29 22:27:49 +00:00
#ifndef LOVR_USE_OCULUS_MOBILE
void lovrPlatformGetFramebufferSize(int* width, int* height) {
*width = 0;
*height = 0;
}
#endif
void lovrPlatformSwapBuffers() {
//
}
void* lovrPlatformGetProcAddress(const char* function) {
return (void*) eglGetProcAddress(function);
}
void lovrPlatformOnWindowClose(windowCloseCallback callback) {
//
}
2020-01-28 05:10:27 +00:00
void lovrPlatformOnWindowFocus(windowFocusCallback callback) {
//
}
void lovrPlatformOnWindowResize(windowResizeCallback callback) {
//
}
void lovrPlatformOnMouseButton(mouseButtonCallback callback) {
//
}
2019-06-06 03:22:51 +00:00
void lovrPlatformOnKeyboardEvent(keyboardCallback callback) {
//
}
void lovrPlatformGetMousePosition(double* x, double* y) {
*x = *y = 0.;
}
void lovrPlatformSetMouseMode(MouseMode mode) {
//
}
bool lovrPlatformIsMouseDown(MouseButton button) {
return false;
}
bool lovrPlatformIsKeyDown(KeyCode key) {
return false;
}