2013-11-17 23:28:27 +00:00
|
|
|
/* RetroArch - A frontend for libretro.
|
2014-01-01 00:50:59 +00:00
|
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
2017-01-22 12:40:32 +00:00
|
|
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
2015-01-07 17:17:42 +00:00
|
|
|
* Copyright (C) 2012-2015 - Michael Lelli
|
2017-12-12 07:55:31 +00:00
|
|
|
*
|
2013-11-17 23:28:27 +00:00
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2014-10-21 03:05:52 +00:00
|
|
|
#include <glsym/glsym.h>
|
2015-12-05 14:55:26 +00:00
|
|
|
|
2019-06-17 09:18:27 +00:00
|
|
|
#include "../../retroarch.h"
|
2013-11-17 23:28:27 +00:00
|
|
|
|
2013-11-18 00:46:54 +00:00
|
|
|
typedef struct android_camera
|
|
|
|
{
|
2013-11-19 19:20:29 +00:00
|
|
|
jmethodID onCameraInit;
|
|
|
|
jmethodID onCameraFree;
|
|
|
|
jmethodID onCameraPoll;
|
|
|
|
jmethodID onCameraStart;
|
|
|
|
jmethodID onCameraStop;
|
|
|
|
jmethodID onCameraSetTexture;
|
2013-11-18 02:48:44 +00:00
|
|
|
GLuint tex;
|
2013-11-18 00:46:54 +00:00
|
|
|
} androidcamera_t;
|
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
static void *android_camera_init(const char *device, uint64_t caps,
|
|
|
|
unsigned width, unsigned height)
|
2013-11-17 23:28:27 +00:00
|
|
|
{
|
2013-11-20 17:01:45 +00:00
|
|
|
jclass class;
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera_t *androidcamera = NULL;
|
|
|
|
JNIEnv *env = NULL;
|
|
|
|
struct android_app *android_app = (struct android_app*)g_android;
|
|
|
|
|
2013-11-17 23:28:27 +00:00
|
|
|
(void)device;
|
|
|
|
(void)width;
|
|
|
|
(void)height;
|
2013-11-18 00:46:54 +00:00
|
|
|
|
2015-07-12 05:53:46 +00:00
|
|
|
if ((caps & (UINT64_C(1) << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE)) == 0)
|
2013-11-18 00:55:22 +00:00
|
|
|
{
|
|
|
|
RARCH_ERR("androidcamera returns OpenGL texture.\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera = (androidcamera_t*)calloc(1, sizeof(androidcamera_t));
|
2013-11-18 00:46:54 +00:00
|
|
|
if (!androidcamera)
|
|
|
|
return NULL;
|
|
|
|
|
2013-11-20 16:33:19 +00:00
|
|
|
env = jni_thread_getenv();
|
|
|
|
if (!env)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2013-11-20 17:01:45 +00:00
|
|
|
GET_OBJECT_CLASS(env, class, android_app->activity->clazz);
|
|
|
|
if (class == NULL)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraInit, class,
|
|
|
|
"onCameraInit", "()V");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraInit)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraFree, class,
|
|
|
|
"onCameraFree", "()V");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraFree)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraSetTexture, class,
|
|
|
|
"onCameraSetTexture", "(I)V");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraSetTexture)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraStart, class,
|
|
|
|
"onCameraStart", "()V");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraStart)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-19 19:20:29 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraStop, class,
|
|
|
|
"onCameraStop", "()V");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraStop)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-18 00:46:54 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
GET_METHOD_ID(env, androidcamera->onCameraPoll, class,
|
|
|
|
"onCameraPoll", "()Z");
|
2013-11-19 19:20:29 +00:00
|
|
|
if (!androidcamera->onCameraPoll)
|
2013-11-26 20:28:05 +00:00
|
|
|
goto dealloc;
|
2013-11-18 02:48:44 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
CALL_VOID_METHOD(env, android_app->activity->clazz,
|
|
|
|
androidcamera->onCameraInit);
|
2013-11-18 01:06:27 +00:00
|
|
|
|
2013-11-18 00:46:54 +00:00
|
|
|
return androidcamera;
|
2013-11-26 20:28:05 +00:00
|
|
|
dealloc:
|
2014-10-27 03:04:04 +00:00
|
|
|
if (androidcamera)
|
|
|
|
free(androidcamera);
|
2013-11-26 20:28:05 +00:00
|
|
|
return NULL;
|
2013-11-17 23:28:27 +00:00
|
|
|
}
|
|
|
|
|
2013-11-18 00:46:54 +00:00
|
|
|
static void android_camera_free(void *data)
|
2013-11-17 23:28:27 +00:00
|
|
|
{
|
|
|
|
struct android_app *android_app = (struct android_app*)g_android;
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
|
|
|
JNIEnv *env = jni_thread_getenv();
|
|
|
|
|
2013-11-20 16:33:19 +00:00
|
|
|
if (!env)
|
|
|
|
return;
|
2013-11-18 00:46:54 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
CALL_VOID_METHOD(env, android_app->activity->clazz,
|
|
|
|
androidcamera->onCameraFree);
|
2013-11-18 00:46:54 +00:00
|
|
|
|
|
|
|
free(androidcamera);
|
2013-11-17 23:28:27 +00:00
|
|
|
}
|
|
|
|
|
2013-11-18 00:46:54 +00:00
|
|
|
static bool android_camera_start(void *data)
|
2013-11-17 23:28:27 +00:00
|
|
|
{
|
|
|
|
struct android_app *android_app = (struct android_app*)g_android;
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
|
|
|
JNIEnv *env = jni_thread_getenv();
|
|
|
|
|
2013-11-20 16:33:19 +00:00
|
|
|
if (!env)
|
|
|
|
return NULL;
|
2013-11-18 01:06:27 +00:00
|
|
|
|
2013-11-18 02:48:44 +00:00
|
|
|
glGenTextures(1, &androidcamera->tex);
|
2013-11-19 20:13:23 +00:00
|
|
|
glBindTexture(GL_TEXTURE_EXTERNAL_OES, androidcamera->tex);
|
2014-09-08 15:57:18 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
2013-11-19 20:13:23 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2014-09-08 15:57:18 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
|
|
|
|
GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
|
|
|
|
GL_CLAMP_TO_EDGE);
|
2013-11-18 02:48:44 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
CALL_VOID_METHOD_PARAM(env, android_app->activity->clazz,
|
|
|
|
androidcamera->onCameraSetTexture, (int) androidcamera->tex);
|
|
|
|
CALL_VOID_METHOD(env, android_app->activity->clazz,
|
|
|
|
androidcamera->onCameraStart);
|
2013-11-18 02:48:44 +00:00
|
|
|
|
2013-11-17 23:28:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-11-18 00:46:54 +00:00
|
|
|
static void android_camera_stop(void *data)
|
2013-11-17 23:28:27 +00:00
|
|
|
{
|
|
|
|
struct android_app *android_app = (struct android_app*)g_android;
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
|
|
|
JNIEnv *env = jni_thread_getenv();
|
|
|
|
|
2013-11-20 16:33:19 +00:00
|
|
|
if (!env)
|
|
|
|
return;
|
2013-11-18 01:06:27 +00:00
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
CALL_VOID_METHOD(env, android_app->activity->clazz,
|
|
|
|
androidcamera->onCameraStop);
|
2017-12-12 07:55:31 +00:00
|
|
|
|
2013-11-18 02:56:22 +00:00
|
|
|
if (androidcamera->tex)
|
2015-12-20 19:52:23 +00:00
|
|
|
video_driver_texture_unload((uintptr_t*)&androidcamera->tex);
|
2013-11-17 23:28:27 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 15:57:18 +00:00
|
|
|
static bool android_camera_poll(void *data,
|
|
|
|
retro_camera_frame_raw_framebuffer_t frame_raw_cb,
|
2013-11-17 23:28:27 +00:00
|
|
|
retro_camera_frame_opengl_texture_t frame_gl_cb)
|
|
|
|
{
|
2016-09-08 11:29:50 +00:00
|
|
|
jboolean newFrame;
|
2013-11-17 23:28:27 +00:00
|
|
|
struct android_app *android_app = (struct android_app*)g_android;
|
2016-09-08 11:29:50 +00:00
|
|
|
androidcamera_t *androidcamera = (androidcamera_t*)data;
|
|
|
|
JNIEnv *env = jni_thread_getenv();
|
|
|
|
|
2013-11-20 16:33:19 +00:00
|
|
|
if (!env)
|
|
|
|
return NULL;
|
|
|
|
|
2013-11-18 01:06:27 +00:00
|
|
|
(void)frame_raw_cb;
|
|
|
|
|
2017-12-12 07:55:31 +00:00
|
|
|
CALL_BOOLEAN_METHOD(env, newFrame, android_app->activity->clazz,
|
2014-09-08 15:57:18 +00:00
|
|
|
androidcamera->onCameraPoll);
|
2013-11-18 01:06:27 +00:00
|
|
|
|
2013-11-18 02:48:44 +00:00
|
|
|
if (newFrame)
|
2013-11-18 01:06:27 +00:00
|
|
|
{
|
2017-12-12 07:55:31 +00:00
|
|
|
/* FIXME: Identity for now. Use proper texture matrix as
|
2014-09-08 15:57:18 +00:00
|
|
|
* returned by Android Camera. */
|
2013-11-18 08:32:29 +00:00
|
|
|
static const float affine[] = {
|
|
|
|
1.0f, 0.0f, 0.0f,
|
|
|
|
0.0f, 1.0f, 0.0f,
|
|
|
|
0.0f, 0.0f, 1.0f
|
|
|
|
};
|
|
|
|
|
2013-11-18 02:48:44 +00:00
|
|
|
if (frame_gl_cb)
|
2013-11-18 08:32:29 +00:00
|
|
|
frame_gl_cb(androidcamera->tex,
|
2013-11-19 20:13:23 +00:00
|
|
|
GL_TEXTURE_EXTERNAL_OES,
|
2013-11-18 08:32:29 +00:00
|
|
|
affine);
|
2013-11-18 01:06:27 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2013-11-17 23:28:27 +00:00
|
|
|
}
|
|
|
|
|
2014-09-11 05:06:20 +00:00
|
|
|
camera_driver_t camera_android = {
|
2013-11-18 00:46:54 +00:00
|
|
|
android_camera_init,
|
|
|
|
android_camera_free,
|
|
|
|
android_camera_start,
|
|
|
|
android_camera_stop,
|
|
|
|
android_camera_poll,
|
2013-11-17 23:28:27 +00:00
|
|
|
"android",
|
|
|
|
};
|