GLSurfaceView: remove old implementation, import the one from AOSP

Now that we have a reasonably well working SurfaceView implementation,
it is actually cleaner to just implement GLSurfaceView the way AOSP
does. In fact, their code doesn't have any weird dependencies, and
can mostly be used as-is.

The AOSP code is pure Java, which means we had to implement some
EGL wrappers.

This change fixes issues with Wayland (it only ever worked because
the pbuffers were allocated using an XWayland EGLDisplay), and
with resizing (which we simply didn't support), all while getting
rid of quite some (arguably not very readable) LoC.
This commit is contained in:
Mis012
2023-10-20 20:54:37 +02:00
parent 621cb866c1
commit 9ef2151c5e
19 changed files with 2140 additions and 879 deletions

View File

@@ -88,7 +88,6 @@ libtranslationlayer_so = shared_library('translation_layer_main', [
'src/api-impl-jni/widgets/android_widget_EditText.c',
'src/api-impl-jni/widgets/android_widget_ImageButton.c',
'src/api-impl-jni/widgets/android_widget_ScrollView.c',
'src/api-impl-jni/widgets/android_opengl_GLSurfaceView.c',
'src/api-impl-jni/widgets/android_widget_ImageView.c',
'src/api-impl-jni/widgets/android_widget_FrameLayout.c',
'src/api-impl-jni/widgets/WrapperWidget.c',

View File

@@ -3,6 +3,8 @@
#include "../defines.h"
#include "../util.h"
#include "../../libandroid/native_window.h"
#include "../generated_headers/com_google_android_gles_jni_EGLImpl.h"
// helpers from android source (TODO: either use GetIntArrayElements, or figure out if GetPrimitiveArrayCritical is superior and use it everywhere if so)
@@ -67,3 +69,59 @@ JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1egl
return ret;
}
JNIEXPORT jlong JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglCreateWindowSurface(JNIEnv *env, jobject this, jlong display, jlong config, jobject surface, jintArray _attrib_list)
{
struct ANativeWindow *native_window = ANativeWindow_fromSurface(env, surface);
EGLint *attrib_list = get_int_array_crit(env, _attrib_list);
EGLSurface ret = bionic_eglCreateWindowSurface(_PTR(display), _PTR(config), native_window, attrib_list);
release_int_array_crit(env, _attrib_list, attrib_list);
return _INTPTR(ret);
}
JNIEXPORT jlong JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglGetDisplay(JNIEnv *env, jobject this, jobject display)
{
return _INTPTR(bionic_eglGetDisplay(0)); // FIXME: why is display passed as an Object??? how do we get an integer from that
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglInitialize(JNIEnv *env, jobject this, jlong display, jintArray _major_minor)
{
EGLint *major_minor = get_int_array_crit(env, _major_minor);
bool ret = eglInitialize(_PTR(display), &major_minor[0], &major_minor[1]);
release_int_array_crit(env, _major_minor, major_minor);
return ret;
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglGetConfigAttrib(JNIEnv *env, jobject this, jlong display, jlong config, jint attribute, jintArray _value)
{
EGLint *value = get_int_array_crit(env, _value);
bool ret = eglGetConfigAttrib(_PTR(display), _PTR(config), attribute, &value[0]);
release_int_array_crit(env, _value, value);
return ret;
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglMakeCurrent(JNIEnv *env, jobject this, jlong display, jlong draw_surface, jlong read_surface, jlong context)
{
return eglMakeCurrent(_PTR(display), _PTR(draw_surface), _PTR(read_surface), _PTR(context));
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglSwapBuffers(JNIEnv *env, jobject this, jlong display, jlong surface)
{
return eglSwapBuffers(_PTR(display), _PTR(surface));
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglDestroySurface(JNIEnv *env, jobject this, jlong display, jlong surface)
{
struct ANativeWindow *native_window = g_hash_table_lookup(egl_surface_hashtable, _PTR(surface));
bool ret = eglDestroySurface(_PTR(display), _PTR(surface));
/* ANativeWindow_fromSurface starts the refcounter at 1, so this will destroy the native window */
ANativeWindow_release(native_window);
return ret;
}
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglDestroyContext(JNIEnv *env, jobject this, jlong display, jlong context)
{
return eglDestroyContext(_PTR(display), _PTR(context));
}

View File

@@ -1,221 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class android_opengl_GLSurfaceView */
#ifndef _Included_android_opengl_GLSurfaceView
#define _Included_android_opengl_GLSurfaceView
#ifdef __cplusplus
extern "C" {
#endif
#undef android_opengl_GLSurfaceView_NO_ID
#define android_opengl_GLSurfaceView_NO_ID -1L
#undef android_opengl_GLSurfaceView_NOT_FOCUSABLE
#define android_opengl_GLSurfaceView_NOT_FOCUSABLE 0L
#undef android_opengl_GLSurfaceView_FOCUSABLE
#define android_opengl_GLSurfaceView_FOCUSABLE 1L
#undef android_opengl_GLSurfaceView_FOCUSABLE_MASK
#define android_opengl_GLSurfaceView_FOCUSABLE_MASK 1L
#undef android_opengl_GLSurfaceView_FITS_SYSTEM_WINDOWS
#define android_opengl_GLSurfaceView_FITS_SYSTEM_WINDOWS 2L
#undef android_opengl_GLSurfaceView_VISIBLE
#define android_opengl_GLSurfaceView_VISIBLE 0L
#undef android_opengl_GLSurfaceView_INVISIBLE
#define android_opengl_GLSurfaceView_INVISIBLE 4L
#undef android_opengl_GLSurfaceView_GONE
#define android_opengl_GLSurfaceView_GONE 8L
#undef android_opengl_GLSurfaceView_VISIBILITY_MASK
#define android_opengl_GLSurfaceView_VISIBILITY_MASK 12L
#undef android_opengl_GLSurfaceView_ENABLED
#define android_opengl_GLSurfaceView_ENABLED 0L
#undef android_opengl_GLSurfaceView_DISABLED
#define android_opengl_GLSurfaceView_DISABLED 32L
#undef android_opengl_GLSurfaceView_ENABLED_MASK
#define android_opengl_GLSurfaceView_ENABLED_MASK 32L
#undef android_opengl_GLSurfaceView_WILL_NOT_DRAW
#define android_opengl_GLSurfaceView_WILL_NOT_DRAW 128L
#undef android_opengl_GLSurfaceView_DRAW_MASK
#define android_opengl_GLSurfaceView_DRAW_MASK 128L
#undef android_opengl_GLSurfaceView_SCROLLBARS_NONE
#define android_opengl_GLSurfaceView_SCROLLBARS_NONE 0L
#undef android_opengl_GLSurfaceView_SCROLLBARS_HORIZONTAL
#define android_opengl_GLSurfaceView_SCROLLBARS_HORIZONTAL 256L
#undef android_opengl_GLSurfaceView_SCROLLBARS_VERTICAL
#define android_opengl_GLSurfaceView_SCROLLBARS_VERTICAL 512L
#undef android_opengl_GLSurfaceView_SCROLLBARS_MASK
#define android_opengl_GLSurfaceView_SCROLLBARS_MASK 768L
#undef android_opengl_GLSurfaceView_FILTER_TOUCHES_WHEN_OBSCURED
#define android_opengl_GLSurfaceView_FILTER_TOUCHES_WHEN_OBSCURED 1024L
#undef android_opengl_GLSurfaceView_OPTIONAL_FITS_SYSTEM_WINDOWS
#define android_opengl_GLSurfaceView_OPTIONAL_FITS_SYSTEM_WINDOWS 2048L
#undef android_opengl_GLSurfaceView_FADING_EDGE_NONE
#define android_opengl_GLSurfaceView_FADING_EDGE_NONE 0L
#undef android_opengl_GLSurfaceView_FADING_EDGE_HORIZONTAL
#define android_opengl_GLSurfaceView_FADING_EDGE_HORIZONTAL 4096L
#undef android_opengl_GLSurfaceView_FADING_EDGE_VERTICAL
#define android_opengl_GLSurfaceView_FADING_EDGE_VERTICAL 8192L
#undef android_opengl_GLSurfaceView_FADING_EDGE_MASK
#define android_opengl_GLSurfaceView_FADING_EDGE_MASK 12288L
#undef android_opengl_GLSurfaceView_CLICKABLE
#define android_opengl_GLSurfaceView_CLICKABLE 16384L
#undef android_opengl_GLSurfaceView_DRAWING_CACHE_ENABLED
#define android_opengl_GLSurfaceView_DRAWING_CACHE_ENABLED 32768L
#undef android_opengl_GLSurfaceView_SAVE_DISABLED
#define android_opengl_GLSurfaceView_SAVE_DISABLED 65536L
#undef android_opengl_GLSurfaceView_SAVE_DISABLED_MASK
#define android_opengl_GLSurfaceView_SAVE_DISABLED_MASK 65536L
#undef android_opengl_GLSurfaceView_WILL_NOT_CACHE_DRAWING
#define android_opengl_GLSurfaceView_WILL_NOT_CACHE_DRAWING 131072L
#undef android_opengl_GLSurfaceView_FOCUSABLE_IN_TOUCH_MODE
#define android_opengl_GLSurfaceView_FOCUSABLE_IN_TOUCH_MODE 262144L
#undef android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_LOW
#define android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_LOW 524288L
#undef android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_HIGH
#define android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_HIGH 1048576L
#undef android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_AUTO
#define android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_AUTO 0L
#undef android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_MASK
#define android_opengl_GLSurfaceView_DRAWING_CACHE_QUALITY_MASK 1572864L
#undef android_opengl_GLSurfaceView_LONG_CLICKABLE
#define android_opengl_GLSurfaceView_LONG_CLICKABLE 2097152L
#undef android_opengl_GLSurfaceView_DUPLICATE_PARENT_STATE
#define android_opengl_GLSurfaceView_DUPLICATE_PARENT_STATE 4194304L
#undef android_opengl_GLSurfaceView_SCROLLBARS_INSIDE_OVERLAY
#define android_opengl_GLSurfaceView_SCROLLBARS_INSIDE_OVERLAY 0L
#undef android_opengl_GLSurfaceView_SCROLLBARS_INSIDE_INSET
#define android_opengl_GLSurfaceView_SCROLLBARS_INSIDE_INSET 16777216L
#undef android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_OVERLAY
#define android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_OVERLAY 33554432L
#undef android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_INSET
#define android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_INSET 50331648L
#undef android_opengl_GLSurfaceView_SCROLLBARS_INSET_MASK
#define android_opengl_GLSurfaceView_SCROLLBARS_INSET_MASK 16777216L
#undef android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_MASK
#define android_opengl_GLSurfaceView_SCROLLBARS_OUTSIDE_MASK 33554432L
#undef android_opengl_GLSurfaceView_SCROLLBARS_STYLE_MASK
#define android_opengl_GLSurfaceView_SCROLLBARS_STYLE_MASK 50331648L
#undef android_opengl_GLSurfaceView_KEEP_SCREEN_ON
#define android_opengl_GLSurfaceView_KEEP_SCREEN_ON 67108864L
#undef android_opengl_GLSurfaceView_SOUND_EFFECTS_ENABLED
#define android_opengl_GLSurfaceView_SOUND_EFFECTS_ENABLED 134217728L
#undef android_opengl_GLSurfaceView_HAPTIC_FEEDBACK_ENABLED
#define android_opengl_GLSurfaceView_HAPTIC_FEEDBACK_ENABLED 268435456L
#undef android_opengl_GLSurfaceView_PARENT_SAVE_DISABLED
#define android_opengl_GLSurfaceView_PARENT_SAVE_DISABLED 536870912L
#undef android_opengl_GLSurfaceView_PARENT_SAVE_DISABLED_MASK
#define android_opengl_GLSurfaceView_PARENT_SAVE_DISABLED_MASK 536870912L
#undef android_opengl_GLSurfaceView_FOCUSABLES_ALL
#define android_opengl_GLSurfaceView_FOCUSABLES_ALL 0L
#undef android_opengl_GLSurfaceView_FOCUSABLES_TOUCH_MODE
#define android_opengl_GLSurfaceView_FOCUSABLES_TOUCH_MODE 1L
#undef android_opengl_GLSurfaceView_FOCUS_BACKWARD
#define android_opengl_GLSurfaceView_FOCUS_BACKWARD 1L
#undef android_opengl_GLSurfaceView_FOCUS_FORWARD
#define android_opengl_GLSurfaceView_FOCUS_FORWARD 2L
#undef android_opengl_GLSurfaceView_FOCUS_LEFT
#define android_opengl_GLSurfaceView_FOCUS_LEFT 17L
#undef android_opengl_GLSurfaceView_FOCUS_UP
#define android_opengl_GLSurfaceView_FOCUS_UP 33L
#undef android_opengl_GLSurfaceView_FOCUS_RIGHT
#define android_opengl_GLSurfaceView_FOCUS_RIGHT 66L
#undef android_opengl_GLSurfaceView_FOCUS_DOWN
#define android_opengl_GLSurfaceView_FOCUS_DOWN 130L
#undef android_opengl_GLSurfaceView_MEASURED_SIZE_MASK
#define android_opengl_GLSurfaceView_MEASURED_SIZE_MASK 16777215L
#undef android_opengl_GLSurfaceView_MEASURED_STATE_MASK
#define android_opengl_GLSurfaceView_MEASURED_STATE_MASK -16777216L
#undef android_opengl_GLSurfaceView_MEASURED_HEIGHT_STATE_SHIFT
#define android_opengl_GLSurfaceView_MEASURED_HEIGHT_STATE_SHIFT 16L
#undef android_opengl_GLSurfaceView_MEASURED_STATE_TOO_SMALL
#define android_opengl_GLSurfaceView_MEASURED_STATE_TOO_SMALL 16777216L
#undef android_opengl_GLSurfaceView_PFLAG2_DRAG_CAN_ACCEPT
#define android_opengl_GLSurfaceView_PFLAG2_DRAG_CAN_ACCEPT 1L
#undef android_opengl_GLSurfaceView_PFLAG2_DRAG_HOVERED
#define android_opengl_GLSurfaceView_PFLAG2_DRAG_HOVERED 2L
#undef android_opengl_GLSurfaceView_LAYOUT_DIRECTION_LTR
#define android_opengl_GLSurfaceView_LAYOUT_DIRECTION_LTR 0L
#undef android_opengl_GLSurfaceView_LAYOUT_DIRECTION_RTL
#define android_opengl_GLSurfaceView_LAYOUT_DIRECTION_RTL 1L
#undef android_opengl_GLSurfaceView_LAYOUT_DIRECTION_INHERIT
#define android_opengl_GLSurfaceView_LAYOUT_DIRECTION_INHERIT 2L
#undef android_opengl_GLSurfaceView_LAYOUT_DIRECTION_LOCALE
#define android_opengl_GLSurfaceView_LAYOUT_DIRECTION_LOCALE 3L
#undef android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT
#define android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT 2L
#undef android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK
#define android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_MASK 12L
#undef android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
#define android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL 16L
#undef android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED
#define android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED 32L
#undef android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
#define android_opengl_GLSurfaceView_PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK 48L
#undef android_opengl_GLSurfaceView_STATUS_BAR_HIDDEN
#define android_opengl_GLSurfaceView_STATUS_BAR_HIDDEN 1L
#undef android_opengl_GLSurfaceView_STATUS_BAR_VISIBLE
#define android_opengl_GLSurfaceView_STATUS_BAR_VISIBLE 0L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_FULLSCREEN
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_FULLSCREEN 4L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_HIDE_NAVIGATION
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_HIDE_NAVIGATION 2L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_IMMERSIVE
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_IMMERSIVE 2048L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_IMMERSIVE_STICKY
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_IMMERSIVE_STICKY 4096L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 1024L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 512L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_STABLE
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LAYOUT_STABLE 256L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LOW_PROFILE
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_LOW_PROFILE 1L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_VISIBLE
#define android_opengl_GLSurfaceView_SYSTEM_UI_FLAG_VISIBLE 0L
#undef android_opengl_GLSurfaceView_SYSTEM_UI_LAYOUT_FLAGS
#define android_opengl_GLSurfaceView_SYSTEM_UI_LAYOUT_FLAGS 1536L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_CENTER
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_CENTER 4L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_GRAVITY
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_GRAVITY 1L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_INHERIT
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_INHERIT 0L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_TEXT_END
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_TEXT_END 3L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_TEXT_START
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_TEXT_START 2L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_VIEW_END
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_VIEW_END 6L
#undef android_opengl_GLSurfaceView_TEXT_ALIGNMENT_VIEW_START
#define android_opengl_GLSurfaceView_TEXT_ALIGNMENT_VIEW_START 5L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_ANY_RTL
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_ANY_RTL 2L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_FIRST_STRONG
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_FIRST_STRONG 1L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_INHERIT
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_INHERIT 0L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_LOCALE
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_LOCALE 5L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_LTR
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_LTR 3L
#undef android_opengl_GLSurfaceView_TEXT_DIRECTION_RTL
#define android_opengl_GLSurfaceView_TEXT_DIRECTION_RTL 4L
/*
* Class: android_opengl_GLSurfaceView
* Method: native_constructor
* Signature: (Landroid/content/Context;Landroid/util/AttributeSet;)J
*/
JNIEXPORT jlong JNICALL Java_android_opengl_GLSurfaceView_native_1constructor
(JNIEnv *, jobject, jobject, jobject);
/*
* Class: android_opengl_GLSurfaceView
* Method: native_set_renderer
* Signature: (Landroid/opengl/GLSurfaceView/Renderer;)V
*/
JNIEXPORT void JNICALL Java_android_opengl_GLSurfaceView_native_1set_1renderer
(JNIEnv *, jobject, jobject);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -23,6 +23,70 @@ JNIEXPORT jlong JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglCre
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglChooseConfig
(JNIEnv *, jobject, jlong, jintArray, jlongArray, jint, jintArray);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglCreateWindowSurface
* Signature: (JJLandroid/view/Surface;[I)J
*/
JNIEXPORT jlong JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglCreateWindowSurface
(JNIEnv *, jobject, jlong, jlong, jobject, jintArray);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglGetDisplay
* Signature: (Ljava/lang/Object;)J
*/
JNIEXPORT jlong JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglGetDisplay
(JNIEnv *, jobject, jobject);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglInitialize
* Signature: (J[I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglInitialize
(JNIEnv *, jobject, jlong, jintArray);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglGetConfigAttrib
* Signature: (JJI[I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglGetConfigAttrib
(JNIEnv *, jobject, jlong, jlong, jint, jintArray);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglMakeCurrent
* Signature: (JJJJ)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglMakeCurrent
(JNIEnv *, jobject, jlong, jlong, jlong, jlong);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglSwapBuffers
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglSwapBuffers
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglDestroySurface
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglDestroySurface
(JNIEnv *, jobject, jlong, jlong);
/*
* Class: com_google_android_gles_jni_EGLImpl
* Method: native_eglDestroyContext
* Signature: (JJ)Z
*/
JNIEXPORT jboolean JNICALL Java_com_google_android_gles_1jni_EGLImpl_native_1eglDestroyContext
(JNIEnv *, jobject, jlong, jlong);
#ifdef __cplusplus
}
#endif

View File

@@ -87,24 +87,15 @@ void set_up_handle_cache(JNIEnv *env)
handle_cache.canvas.class = _REF((*env)->FindClass(env, "android/graphics/Canvas"));
handle_cache.canvas.constructor = _METHOD(handle_cache.canvas.class, "<init>", "(JJ)V");
handle_cache.renderer.class = _REF((*env)->FindClass(env, "android/opengl/GLSurfaceView$Renderer"));
handle_cache.renderer.onSurfaceCreated = _METHOD(handle_cache.renderer.class, "onSurfaceCreated", "(Ljavax/microedition/khronos/opengles/GL10;Ljavax/microedition/khronos/egl/EGLConfig;)V");
handle_cache.renderer.onSurfaceChanged = _METHOD(handle_cache.renderer.class, "onSurfaceChanged", "(Ljavax/microedition/khronos/opengles/GL10;II)V");
handle_cache.renderer.onDrawFrame = _METHOD(handle_cache.renderer.class, "onDrawFrame", "(Ljavax/microedition/khronos/opengles/GL10;)V");
handle_cache.gl_surface_view.class = _REF((*env)->FindClass(env, "android/opengl/GLSurfaceView"));
handle_cache.gl_surface_view.onTouchEvent = _METHOD(handle_cache.gl_surface_view.class, "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
handle_cache.gl_surface_view.wrap_EGLContextFactory_createContext = _METHOD(handle_cache.gl_surface_view.class, "wrap_EGLContextFactory_createContext", "(JJ)J");
handle_cache.gl_surface_view.wrap_EGLConfigChooser_chooseConfig = _METHOD(handle_cache.gl_surface_view.class, "wrap_EGLConfigChooser_chooseConfig", "(J)J");
handle_cache.audio_track_periodic_listener.class = _REF((*env)->FindClass(env, "android/media/AudioTrack$OnPlaybackPositionUpdateListener"));
handle_cache.audio_track_periodic_listener.onPeriodicNotification = _METHOD(handle_cache.audio_track_periodic_listener.class, "onPeriodicNotification", "(Landroid/media/AudioTrack;)V");
handle_cache.input_queue_callback.class = _REF((*env)->FindClass(env, "android/view/InputQueue$Callback"));
handle_cache.input_queue_callback.onInputQueueCreated = _METHOD(handle_cache.input_queue_callback.class, "onInputQueueCreated", "(Landroid/view/InputQueue;)V");
handle_cache.surface_holder_callback.class = _REF((*env)->FindClass(env, "android/view/SurfaceHolder$Callback"));
handle_cache.surface_holder_callback.surfaceCreated = _METHOD(handle_cache.surface_holder_callback.class, "surfaceCreated", "(Landroid/view/SurfaceHolder;)V");
handle_cache.surface_view.class = _REF((*env)->FindClass(env, "android/view/SurfaceView"));
handle_cache.surface_view.surfaceCreated = _METHOD(handle_cache.surface_view.class, "surfaceCreated", "()V");
handle_cache.surface_view.surfaceChanged = _METHOD(handle_cache.surface_view.class, "surfaceChanged", "(III)V");
handle_cache.view.class = _REF((*env)->FindClass(env, "android/view/View"));
if((*env)->ExceptionCheck(env))

View File

@@ -41,18 +41,6 @@ struct handle_cache {
jclass class;
jmethodID constructor;
} canvas;
struct {
jclass class;
jmethodID onSurfaceCreated;
jmethodID onSurfaceChanged;
jmethodID onDrawFrame;
} renderer;
struct {
jclass class;
jmethodID onTouchEvent;
jmethodID wrap_EGLContextFactory_createContext;
jmethodID wrap_EGLConfigChooser_chooseConfig;
} gl_surface_view;
struct {
jclass class;
jmethodID onPeriodicNotification;
@@ -64,7 +52,8 @@ struct handle_cache {
struct {
jclass class;
jmethodID surfaceCreated;
} surface_holder_callback;
jmethodID surfaceChanged;
} surface_view;
struct {
jclass class;
jmethodID setLayoutParams;

View File

@@ -65,7 +65,6 @@ static gboolean on_event(GtkEventControllerLegacy *event_controller, GdkEvent *e
if(d->num_clicks == 0)
break;
case GDK_TOUCH_UPDATE:
printf("d->num_clicks: %u\n", d->num_clicks);
gdk_event_get_widget_relative_position(event, widget, &x, &y);
call_ontouch_callback(MOTION_EVENT_ACTION_MOVE, x, y, d);
break;

View File

@@ -1,498 +0,0 @@
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glcorearb.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <gtk/gtk.h>
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/wayland/gdkwayland.h>
#endif
#include "../defines.h"
#include "../util.h"
#include "WrapperWidget.h"
#include "../generated_headers/android_opengl_GLSurfaceView.h"
#define SOURCE_TOUCHSCREEN 4098
// for whatever reason, some Mesa builds don't export the OES function (which we use in order to have GLESv1 support)
GL_APICALL void GL_APIENTRY _glEGLImageTargetTexture2DOES_load(GLenum target, GLeglImageOES image);
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC _glEGLImageTargetTexture2DOES = &_glEGLImageTargetTexture2DOES_load;
GL_APICALL void GL_APIENTRY _glEGLImageTargetTexture2DOES_load(GLenum target, GLeglImageOES image)
{
_glEGLImageTargetTexture2DOES =
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
_glEGLImageTargetTexture2DOES(target, image);
}
GL_APICALL void GL_APIENTRY __attribute__((weak)) glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image)
{
_glEGLImageTargetTexture2DOES(target, image);
}
// end of OES workaround
//#define FIXME__WIDTH 540
//#define FIXME__HEIGHT 960
// FIXME: what do we do here? we should probably take these from the size of the GLArea, but how do we change the sizes of all the textures and buffers etc when the GLArea changes size?
// for now, borrow the initial app window width/height
extern int FIXME__WIDTH;
extern int FIXME__HEIGHT;
// mainly frame markers (very obtrusive, not recommended for most builds)
#ifdef DEBUG_GLAREA
#define d_printf(...) printf(__VA_ARGS__)
#else
#define d_printf(...)
#endif
#define ___GL_TRACE___(message) glDebugMessageInsert(GL_DEBUG_SOURCE_THIRD_PARTY, GL_DEBUG_TYPE_MARKER, 0xdeadbeef, GL_DEBUG_SEVERITY_NOTIFICATION, strlen(message), message)
JNIEXPORT jlong JNICALL Java_android_opengl_GLSurfaceView_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs)
{
GtkWidget *wrapper = g_object_ref(wrapper_widget_new());
gtk_widget_set_vexpand(wrapper, TRUE);
GtkWidget *gl_area = gtk_gl_area_new();
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), gl_area);
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
return _INTPTR(gl_area);
}
//two triangles put together to make a square
const float positions[] = {
-1, -1, 0,
-1, 1, 0,
1, -1, 0,
1, -1, 0,
-1, 1, 0,
1, 1, 0
};
const char *vertexStr = "#version 320 es\n"
"in vec3 pos;\n"
"out vec2 texCoords;\n"
"void main(){\n"
" texCoords = vec2(pos.x, pos.y);\n"
" gl_Position = vec4((pos.x * 2.0) - 1.0, (pos.y * 2.0) - 1.0, pos.z, 1.0);\n"
"}\n";
const char *fragmentStr = "#version 320 es\n"
"out highp vec4 outputColor;\n"
"in highp vec2 texCoords;\n"
"uniform sampler2D texSampler;\n"
"void main(){\n"
" outputColor = texture(texSampler, texCoords);\n"
"}\n";
struct render_priv {
GLuint program;
GLuint vao;
int texUnit;
GLuint texBufferdObject;
GLuint sampler;
/* --- */
EGLSurface eglSurface;
EGLContext eglContext;
GLuint FramebufferName;
GLuint renderedTexture;
GLuint texture_id;
EGLImage egl_image;
};
static void check_shader_compile_error(GLuint shader)
{
GLint compileResult;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
if(compileResult != GL_TRUE) {
GLint log_size = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_size);
GLchar *info_log = malloc(log_size);
glGetShaderInfoLog(shader, log_size, &log_size, info_log);
fprintf(stderr, "\nError compiling one of the shaders used by GLSurfaceView:\n%s\n---\nsince this error shouldn't ever happen, we fail hard\n", info_log);
free(info_log);
exit(1);
}
}
static void check_program_link_error(GLuint program)
{
GLint link_status = 0;
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
if(link_status != GL_TRUE) {
GLint log_size = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
GLchar *info_log = malloc(log_size);
glGetProgramInfoLog(program, log_size, &log_size, info_log);
fprintf(stderr, "\nError linking the program used by GLSurfaceView:\n%s\n---\nsince this error shouldn't ever happen, we fail hard\n", info_log);
free(info_log);
exit(1);
}
}
#define check_egl_error() \
do { \
EGLint error_ = eglGetError(); \
if(error_ != EGL_SUCCESS) \
fprintf(stderr, "\nError in %s (%s:%d): \n" \
"eglGetError reported 0x%x\n" \
"this might be because we need to implement more stuff, so we will continue from here\n", \
__func__, __FILE__, __LINE__, error_); \
} while(0)
// TODO: use this where appropriate
#define check_gl_error() \
do { \
GLenum error_ = glGetError(); \
if(error_ != GL_NO_ERROR) \
fprintf(stderr, "\nError in %s (%s:%d): \n" \
"glGetError reported 0x%x\n" \
"this might be because we need to implement more stuff, so we will continue from here\n", \
__func__, __FILE__, __LINE__, error_); \
} while(0)
struct jni_gl_callback_data { JavaVM *jvm; jobject this; jobject renderer; bool first_time;};
static void on_realize(GtkGLArea *gl_area, struct jni_gl_callback_data *d)
{
// ---
// compensate for offset between the widget coordinates and the surface coordinates
double off_x;
double off_y;
GtkWidget *window = GTK_WIDGET(gtk_widget_get_native(gl_area));
gtk_native_get_surface_transform(GTK_NATIVE(window), &off_x, &off_y);
FIXME__WIDTH -= off_x;
FIXME__HEIGHT -= off_y;
// ---
gtk_gl_area_make_current(gl_area);
struct render_priv *render_priv = g_object_get_data(G_OBJECT(gl_area), "render_priv");
JNIEnv *env;
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
EGLNativeDisplayType display_id = EGL_DEFAULT_DISPLAY;
#ifdef GDK_WINDOWING_WAYLAND
GdkDisplay *gdk_dpy = gdk_display_get_default();
if (GDK_IS_WAYLAND_DISPLAY(gdk_dpy)) {
display_id = (EGLNativeDisplayType)gdk_wayland_display_get_wl_display(gdk_dpy);
}
#endif
EGLDisplay eglDisplay = eglGetDisplay(display_id);
EGLDisplay old_eglDisplay = eglGetCurrentDisplay();
d_printf("GTK version: >%d__%d__%d<\n", gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version());
d_printf("OpenGL version: >%s<\n", glGetString(GL_VERSION));
glGenTextures(1, &render_priv->texture_id);
// vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexStr, NULL);
glCompileShader(vertexShader);
check_shader_compile_error(vertexShader);
// fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentStr, NULL);
glCompileShader(fragmentShader);
check_shader_compile_error(fragmentShader);
// program
render_priv->program = glCreateProgram();
glAttachShader(render_priv->program, vertexShader);
glAttachShader(render_priv->program, fragmentShader);
glLinkProgram(render_priv->program);
check_program_link_error(render_priv->program);
glUseProgram(render_priv->program);
// the triangles
glGenVertexArrays(1, &render_priv->vao);
glBindVertexArray(render_priv->vao);
GLuint positionBufferObject;
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*6*3,positions, GL_STREAM_DRAW);
GLuint posIndex = glGetAttribLocation(render_priv->program, "pos");
glEnableVertexAttribArray(posIndex);
glVertexAttribPointer(posIndex, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
glUseProgram(render_priv->program);
// the texture we will be rendering to
glGenTextures(1, &render_priv->texBufferdObject);
glBindTexture(GL_TEXTURE_2D, render_priv->texBufferdObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// texture sampler for our triangles
glGenSamplers(1, &render_priv->sampler);
glSamplerParameteri(render_priv->sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(render_priv->sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(render_priv->sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLuint samplerUniform = glGetUniformLocation(render_priv->program, "texSampler");
glUniform1i(samplerUniform, render_priv->texUnit);
glUseProgram(0);
// EGL setup
eglInitialize(eglDisplay, 0, 0);
eglBindAPI(EGL_OPENGL_ES_API);
EGLConfig eglConfig;
// a roundabout way to let the app define the parameter list, and then choose the best fit out of all the returned configs
eglConfig = (EGLConfig)_PTR((*env)->CallLongMethod(env, d->this, handle_cache.gl_surface_view.wrap_EGLConfigChooser_chooseConfig, _INTPTR(eglDisplay)));
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
check_egl_error();
// set up the pbuffer (TODO: is there any way to dynamically change the width/height?)
EGLint pbufferAttribs[5];
pbufferAttribs[0] = EGL_WIDTH;
pbufferAttribs[1] = FIXME__WIDTH;
pbufferAttribs[2] = EGL_HEIGHT;
pbufferAttribs[3] = FIXME__HEIGHT;
pbufferAttribs[4] = EGL_NONE;
render_priv->eglSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, pbufferAttribs);
check_egl_error();
// a roundabout way to run eglCreateContext with the atrribute list that the app chose
render_priv->eglContext = (EGLContext)_PTR((*env)->CallLongMethod(env, d->this, handle_cache.gl_surface_view.wrap_EGLContextFactory_createContext, _INTPTR(eglDisplay), _INTPTR(eglConfig)));
check_egl_error();
// save the EGL state before we change it, so we can switch back later
EGLContext old_eglContext = eglGetCurrentContext();
EGLSurface old_read_surface = eglGetCurrentSurface(EGL_READ);
EGLSurface old_draw_surface = eglGetCurrentSurface(EGL_DRAW);
bool result = eglMakeCurrent(eglDisplay, render_priv->eglSurface, render_priv->eglSurface, render_priv->eglContext);
check_egl_error();
// set up the framebuffer
glGenFramebuffers(1, &render_priv->FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, render_priv->FramebufferName);
check_gl_error();
glGenTextures(1, &render_priv->renderedTexture);
glBindTexture(GL_TEXTURE_2D, render_priv->renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, FIXME__WIDTH, FIXME__HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
check_gl_error();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
check_gl_error();
GLuint depthrenderbuffer;
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, FIXME__WIDTH, FIXME__HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
check_gl_error();
// Set "renderedTexture" as our colour attachement #0
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_priv->renderedTexture, 0);
check_gl_error();
// Set the list of draw buffers.
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
check_gl_error();
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr, "Error: glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE\n");
// create the EGL Image which we will use to access the rendered-to texture from Gtk's EGL context
render_priv->egl_image = eglCreateImage(eglDisplay, render_priv->eglContext, EGL_GL_TEXTURE_2D, (EGLClientBuffer)(intptr_t)render_priv->renderedTexture, NULL);
check_egl_error();
// the GLSurfaceView implements SurfaceHolder.Callback, and the app may expect that we call the `surfaceCreated` method
(*env)->CallVoidMethod(env, d->this, handle_cache.surface_holder_callback.surfaceCreated, NULL);
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
// Here we call the app's onSurfaceCreated callback. This is the android API's equivalent of the `realize` callback that we are currently in.
___GL_TRACE___("---- calling onSurfaceCreated");
(*env)->CallVoidMethod(env, d->renderer, handle_cache.renderer.onSurfaceCreated, _GET_OBJ_FIELD(d->this, "java_gl_wrapper", "Ljavax/microedition/khronos/opengles/GL10;"), NULL); // FIXME passing NULL only works if the app doesn't use these parameters
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
___GL_TRACE___("---- returned from calling onSurfaceCreated");
// This should be called from Gtk's `resize` callback. However, until we figure out how to resize the pbuffer, the framebuffer, and the texture, we can't afford to pass the actual widget's dimensions here
___GL_TRACE___("---- calling onSurfaceChanged");
(*env)->CallVoidMethod(env, d->renderer, handle_cache.renderer.onSurfaceChanged, NULL, FIXME__WIDTH, FIXME__HEIGHT); // FIXME put this in the right callback (and pass the actual dimensions)
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
___GL_TRACE___("---- returned from calling onSurfaceChanged");
// restore the EGL context so that Gtk doesn't get confused
result = eglMakeCurrent(old_eglDisplay, old_read_surface, old_draw_surface, old_eglContext);
check_egl_error();
}
static gboolean render(GtkGLArea *gl_area, GdkGLContext *context, struct jni_gl_callback_data *d)
{
struct render_priv *render_priv = g_object_get_data(G_OBJECT(gl_area), "render_priv");
JNIEnv *env;
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
EGLNativeDisplayType display_id = EGL_DEFAULT_DISPLAY;
#ifdef GDK_WINDOWING_WAYLAND
GdkDisplay *gdk_dpy = gdk_display_get_default();
if (GDK_IS_WAYLAND_DISPLAY(gdk_dpy)) {
display_id = (EGLNativeDisplayType)gdk_wayland_display_get_wl_display(gdk_dpy);
}
#endif
EGLDisplay eglDisplay = eglGetDisplay(display_id);
EGLDisplay old_eglDisplay = eglGetCurrentDisplay();
// save the EGL state before we change it, so we can switch back later
EGLContext old_eglContext = eglGetCurrentContext();
EGLSurface old_read_surface = eglGetCurrentSurface(EGL_READ);
EGLSurface old_draw_surface = eglGetCurrentSurface(EGL_DRAW);
bool result = eglMakeCurrent(eglDisplay, render_priv->eglSurface, render_priv->eglSurface, render_priv->eglContext);
check_egl_error();
// bind the framebuffer that we are rendering into
check_gl_error();
glBindFramebuffer(GL_FRAMEBUFFER, render_priv->FramebufferName);
check_gl_error();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_priv->renderedTexture, 0);
check_gl_error();
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
fprintf(stderr, "Error: glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE\n");
d_printf("OpenGL version before calling onDrawFrame: >%s<\n", glGetString(GL_VERSION));
d_printf("\n\n\n---- calling onDrawFrame\n\n");
// this marks the part where the app is doing the rendering (as opposed to Gtk) for easier orientation in a trace (e.g apitrace)
// TODO: make a program that extracts just these fragments from a trace
// TODO: add a unique identifier of this GLArea (worst case the pointer to this widget)
check_gl_error();
___GL_TRACE___("---- calling onDrawFrame");
// Here we call the app's onDrawFrame callback. This is the android API's equivalent of the `render` callback that we are currently in.
(*env)->CallVoidMethod(env, d->renderer, handle_cache.renderer.onDrawFrame, NULL); // FIXME passing NULL only works if the app doesn't use this parameter
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
___GL_TRACE___("---- returned from calling onDrawFrame");
check_gl_error();
d_printf("\n---- returned from calling onDrawFrame\n\n\n\n");
eglSwapBuffers(eglDisplay, render_priv->eglSurface);
// switch the EGL context back to Gtk's one
result = eglMakeCurrent(old_eglDisplay, old_read_surface, old_draw_surface, old_eglContext);
check_egl_error();
gtk_gl_area_make_current(gl_area);
d_printf("OpenGL version after restore: >%s<\n", glGetString(GL_VERSION));
d_printf("\n\n\n---- drawing the texture containing our frame\n\n");
___GL_TRACE___("---- drawing the texture containing our frame");
// draw on a black background (TODO: isn't this pointless?)
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw two triangles (a rectangle) painted with the texture that we were rendering into
glUseProgram(render_priv->program);
glBindVertexArray(render_priv->vao);
glActiveTexture(GL_TEXTURE0 + render_priv->texUnit);
glBindTexture(GL_TEXTURE_2D, render_priv->texBufferdObject);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, render_priv->egl_image);
glBindSampler(render_priv->texUnit, render_priv->sampler);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
___GL_TRACE___("---- end of drawing the texture containing our frame");
d_printf("\n---- end of drawing the texture containing our frame\n\n\n\n");
return TRUE;
}
extern gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data);
JNIEXPORT void JNICALL Java_android_opengl_GLSurfaceView_native_1set_1renderer(JNIEnv *env, jobject this, jobject renderer)
{
GtkWidget *gl_area = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget")));
gtk_gl_area_set_has_stencil_buffer(GTK_GL_AREA(gl_area), true); // FIXME don't assume what the app wants
gtk_gl_area_set_has_depth_buffer(GTK_GL_AREA(gl_area), true);
gtk_gl_area_set_use_es(GTK_GL_AREA(gl_area), true); // FIXME
struct render_priv *render_priv = malloc(sizeof(struct render_priv));
render_priv->texUnit = 0;
render_priv->sampler = 0;
render_priv->FramebufferName = 0;
g_object_set_data(G_OBJECT(gl_area), "render_priv", render_priv);
JavaVM *jvm;
(*env)->GetJavaVM(env, &jvm);
struct jni_gl_callback_data *gl_callback_data = malloc(sizeof(struct jni_gl_callback_data));
gl_callback_data->jvm = jvm;
gl_callback_data->this = _REF(this);
gl_callback_data->renderer = _REF(renderer);
gl_callback_data->first_time = 1;
g_signal_connect(gl_area, "render", G_CALLBACK(render), gl_callback_data);
g_signal_connect(gl_area, "realize", G_CALLBACK(on_realize), gl_callback_data);
gtk_widget_add_tick_callback(gl_area, tick_callback, NULL, NULL);
//FIXME
gtk_widget_set_hexpand(gtk_widget_get_parent(GTK_WIDGET(gl_area)), true);
}

View File

@@ -78,9 +78,16 @@ static void on_resize(GtkWidget* self, gint width, gint height, struct jni_callb
// TODO: are there cases where returning RGBA_8888 is a bad idea?
// NOTE: we want to call the private method of android.view.SurfaceView, not the related method with this name in the API
(*env)->CallVoidMethod(env, d->this, _METHOD(d->this_class, "surfaceChanged", "(Landroid/view/SurfaceHolder;III)V"),
_GET_OBJ_FIELD(d->this, "mSurfaceHolder", "Landroid/view/SurfaceHolder;"), 1 /*RGBA_8888*/,
width, height);
(*env)->CallVoidMethod(env, d->this, handle_cache.surface_view.surfaceChanged, 1 /*RGBA_8888*/, width, height);
}
static void on_realize(GtkWidget* self, struct jni_callback_data *d)
{
JNIEnv *env;
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
// NOTE: we want to call the private method of android.view.SurfaceView, not the related method with this name in the API
(*env)->CallVoidMethod(env, d->this, handle_cache.surface_view.surfaceCreated);
}
JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs)
@@ -89,6 +96,7 @@ JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv
GtkWidget *dummy = surface_view_widget_new();
gtk_widget_set_name(dummy, "dummy widget for SurfaceView");
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), dummy);
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
// TODO: is this correct for all usecases? how do we know when it's not?
gtk_widget_set_hexpand(wrapper, true);
gtk_widget_set_vexpand(wrapper, true);
@@ -102,6 +110,7 @@ JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv
callback_data->this_class = _REF((*env)->FindClass(env, "android/view/SurfaceView"));
g_signal_connect(dummy, "resize", G_CALLBACK(on_resize), callback_data);
g_signal_connect(dummy, "realize", G_CALLBACK(on_realize), callback_data);
return _INTPTR(dummy);
}

View File

@@ -33,6 +33,7 @@ public class MediaPlayer {
public void setOnSeekCompleteListener(MediaPlayer.OnSeekCompleteListener dummy) {}
public void setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener dummy) {}
public void setAudioStreamType(int dummy) {}
public void pause() {}
public void prepareAsync() {}
public void reset() {}
public void release() {}

File diff suppressed because it is too large Load Diff

View File

@@ -23,12 +23,18 @@ public class SurfaceView extends View {
mSurface.widget = this.widget;
}
private void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
private void surfaceChanged(int format, int width, int height) {
for (SurfaceHolder.Callback c : mCallbacks) {
c.surfaceChanged(mSurfaceHolder, format, width, height);
}
}
private void surfaceCreated() {
for (SurfaceHolder.Callback c : mCallbacks) {
c.surfaceCreated(mSurfaceHolder);
}
}
@Override
protected native long native_constructor(Context context, AttributeSet attrs);

View File

@@ -1,5 +1,24 @@
/*
* parts of this file Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gles_jni;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import javax.microedition.khronos.egl.*;
public class EGLImpl implements EGL10 {
@@ -36,21 +55,78 @@ public class EGLImpl implements EGL10 {
return ret;
}
public EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list) {
Surface sur = null;
if (native_window instanceof SurfaceView) {
SurfaceView surfaceView = (SurfaceView)native_window;
sur = surfaceView.getHolder().getSurface();
} else if (native_window instanceof SurfaceHolder) {
SurfaceHolder holder = (SurfaceHolder)native_window;
sur = holder.getSurface();
} else if (native_window instanceof Surface) {
sur = (Surface)native_window;
}
long eglSurfaceId;
if (sur != null) {
eglSurfaceId = native_eglCreateWindowSurface(display.native_egl_display, config.native_egl_config, sur, attrib_list);
} /*else if (native_window instanceof SurfaceTexture) {
eglSurfaceId = native_eglCreateWindowSurfaceTexture(display, config,
native_window, attrib_list);
}*/ else {
throw new java.lang.UnsupportedOperationException(
"eglCreateWindowSurface() can only be called with an instance of "
+
"Surface, SurfaceView, SurfaceHolder or [FIXME]SurfaceTexture at the moment.");
}
if (eglSurfaceId == 0) {
return EGL10.EGL_NO_SURFACE;
}
return new EGLSurfaceImpl(eglSurfaceId);
}
public EGLDisplay eglGetDisplay(Object display) {
long native_display = native_eglGetDisplay(display);
if (native_display == 0)
return EGL10.EGL_NO_DISPLAY;
return new EGLDisplay(native_display);
}
public boolean eglInitialize(EGLDisplay display, int[] major_minor) {
return native_eglInitialize(display.native_egl_display, major_minor);
}
public boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, int attribute, int[] value) {
return native_eglGetConfigAttrib(display.native_egl_display, config.native_egl_config, attribute, value);
}
public boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context) {
return native_eglMakeCurrent(display.native_egl_display, ((EGLSurfaceImpl)draw).mEGLSurface, ((EGLSurfaceImpl)read).mEGLSurface, context.native_egl_context);
}
public boolean eglSwapBuffers(EGLDisplay display, EGLSurface surface) {
return native_eglSwapBuffers(display.native_egl_display, ((EGLSurfaceImpl)surface).mEGLSurface);
}
public boolean eglDestroySurface(EGLDisplay display, EGLSurface surface) {
return native_eglDestroySurface(display.native_egl_display, ((EGLSurfaceImpl)surface).mEGLSurface);
}
public boolean eglDestroyContext(EGLDisplay display, EGLContext context) {
return native_eglDestroyContext(display.native_egl_display, context.native_egl_context);
}
/* STUBS */
public boolean eglCopyBuffers(EGLDisplay display, EGLSurface surface, Object native_pixmap) { return false; }
public EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list) { return null; }
public EGLSurface eglCreatePixmapSurface(EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list) { return null; }
public EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list) { return null; }
public boolean eglDestroyContext(EGLDisplay display, EGLContext context) { return false; }
public boolean eglDestroySurface(EGLDisplay display, EGLSurface surface) { return false; }
public boolean eglGetConfigAttrib(EGLDisplay display, EGLConfig config, int attribute, int[] value) { return false; }
public boolean eglGetConfigs(EGLDisplay display, EGLConfig[] configs, int config_size, int[] num_config) { return false; }
public EGLContext eglGetCurrentContext() { return null; }
public EGLDisplay eglGetCurrentDisplay() { return null; }
public EGLSurface eglGetCurrentSurface(int readdraw) { return null; }
public EGLDisplay eglGetDisplay(Object native_display) { return null; }
public int eglGetError() { return EGL_SUCCESS; } // don't let yourself get fooled, this is also a stub :P
public boolean eglInitialize(EGLDisplay display, int[] major_minor) { return false; }
public boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context) { return false; }
public boolean eglQueryContext(EGLDisplay display, EGLContext context, int attribute, int[] value) { return false; }
public String eglQueryString(EGLDisplay display, int name) { return "FIXME"; }
public boolean eglQuerySurface(EGLDisplay display, EGLSurface surface, int attribute, int[] value) { return false; }
@@ -58,8 +134,16 @@ public class EGLImpl implements EGL10 {
* @hide *
*/
public boolean eglReleaseThread() { return false; }
public boolean eglSwapBuffers(EGLDisplay display, EGLSurface surface) { return false; }
public boolean eglTerminate(EGLDisplay display) { return false; }
public boolean eglWaitGL() { return false; }
public boolean eglWaitNative(int engine, Object bindTarget) { return false; }
private native long native_eglCreateWindowSurface(long native_egl_display, long native_egl_config, Surface surface, int[] attrib_list);
private native long native_eglGetDisplay(Object native_display);
private native boolean native_eglInitialize(long native_egl_display, int[] major_minor);
private native boolean native_eglGetConfigAttrib(long native_egl_display, long native_edl_config, int attribute, int[] value);
private native boolean native_eglMakeCurrent(long native_egl_display, long native_draw_surface, long native_read_surface, long native_context);
private native boolean native_eglSwapBuffers(long native_egl_display, long native_surface);
private native boolean native_eglDestroySurface(long native_egl_display, long native_surface);
private native boolean native_eglDestroyContext(long native_egl_display, long native_context);
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.gles_jni;
import javax.microedition.khronos.egl.*;
public class EGLSurfaceImpl extends EGLSurface {
public long mEGLSurface;
private long mNativePixelRef;
public EGLSurfaceImpl() {
mEGLSurface = 0;
mNativePixelRef = 0;
}
public EGLSurfaceImpl(long surface) {
mEGLSurface = surface;
mNativePixelRef = 0;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
EGLSurfaceImpl that = (EGLSurfaceImpl)o;
return mEGLSurface == that.mEGLSurface;
}
}

View File

@@ -91,9 +91,9 @@ public interface EGL10 extends EGL {
int EGL_WINDOW_BIT = 0x04;
Object EGL_DEFAULT_DISPLAY = null;
EGLDisplay EGL_NO_DISPLAY = null; // new com.google.android.gles_jni.EGLDisplayImpl(0);
EGLContext EGL_NO_CONTEXT = null; // new com.google.android.gles_jni.EGLContextImpl(0);
EGLSurface EGL_NO_SURFACE = null; // new com.google.android.gles_jni.EGLSurfaceImpl(0);
EGLDisplay EGL_NO_DISPLAY = new javax.microedition.khronos.egl.EGLDisplay(0);
EGLContext EGL_NO_CONTEXT = new javax.microedition.khronos.egl.EGLContext(0);
EGLSurface EGL_NO_SURFACE = new com.google.android.gles_jni.EGLSurfaceImpl(0);
boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config);
boolean eglCopyBuffers(EGLDisplay display, EGLSurface surface, Object native_pixmap);

View File

@@ -440,6 +440,7 @@ hax_jar = jar('hax', [
'com/android/org/conscrypt/OpenSSLSocketFactoryImpl.java',
'com/android/org/conscrypt/SSLParametersImpl.java',
'com/google/android/gles_jni/EGLImpl.java',
'com/google/android/gles_jni/EGLSurfaceImpl.java',
'com/google/android/gles_jni/GLImpl.java',
'com/google/android/vending/expansion/downloader/IDownloaderClient.java',
'com/google/android/vending/expansion/downloader/impl/DownloaderService.java',

View File

@@ -468,21 +468,28 @@ EGLDisplay bionic_eglGetDisplay(NativeDisplayType native_display)
}
}
EGLSurface egl_surface_hashtable;
EGLSurface bionic_eglCreateWindowSurface(EGLDisplay display, EGLConfig config, struct ANativeWindow *native_window, EGLint const *attrib_list)
{
// better than crashing (TODO: check if apps try to use the NULL value anyway)
if(!native_window)
return NULL;
if(!egl_surface_hashtable)
egl_surface_hashtable = g_hash_table_new(NULL, NULL);
PrintConfigAttributes(display, config);
EGLSurface ret = eglCreateWindowSurface(display, config, native_window->egl_window, attrib_list);
EGLSurface surface = eglCreateWindowSurface(display, config, native_window->egl_window, attrib_list);
printf("EGL::: native_window->egl_window: %ld\n", native_window->egl_window);
printf("EGL::: eglGetError: %d\n", eglGetError());
printf("EGL::: ret: %p\n", ret);
printf("EGL::: ret: %p\n", surface);
return ret;
g_hash_table_insert(egl_surface_hashtable, surface, native_window);
return surface;
}
// FIXME 1.5: this most likely belongs elsewhere

View File

@@ -14,4 +14,9 @@ struct ANativeWindow {
int refcount;
};
extern EGLSurface egl_surface_hashtable;
struct ANativeWindow *ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
EGLSurface bionic_eglCreateWindowSurface(EGLDisplay display, EGLConfig config, struct ANativeWindow *native_window, EGLint const *attrib_list);
EGLDisplay bionic_eglGetDisplay(NativeDisplayType native_display);
void ANativeWindow_release(struct ANativeWindow *native_window);

View File

@@ -47,10 +47,6 @@ char *get_app_data_dir()
return app_data_dir;
}
// FIXME: used by hacks in GLSurfaceView
int FIXME__WIDTH;
int FIXME__HEIGHT;
char *construct_classpath(char *prefix, char **cp_array, size_t len)
{
size_t result_len = strlen(prefix);
@@ -335,9 +331,6 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
jclass context_class = (*env)->FindClass(env, "android/content/Context");
_SET_STATIC_OBJ_FIELD(context_class, "apk_path", "Ljava/lang/String;", _JSTRING(apk_classpath));
FIXME__WIDTH = d->window_width;
FIXME__HEIGHT = d->window_height;
window = gtk_application_window_new(app);
if(getenv("ATL_DISABLE_WINDOW_DECORATIONS"))