Index: tools/viewer/sk_app/android/surface_glue_android.cpp |
diff --git a/tools/viewer/sk_app/android/surface_glue_android.cpp b/tools/viewer/sk_app/android/surface_glue_android.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e287afa43b43ea385985ca2c65e70450d01d7464 |
--- /dev/null |
+++ b/tools/viewer/sk_app/android/surface_glue_android.cpp |
@@ -0,0 +1,169 @@ |
+/* |
+* Copyright 2016 Google Inc. |
+* |
+* Use of this source code is governed by a BSD-style license that can be |
+* found in the LICENSE file. |
+*/ |
+ |
+#include "surface_glue_android.h" |
+ |
+#include <jni.h> |
+#include <pthread.h> |
+#include <stdio.h> |
+#include <unistd.h> |
+ |
+#include <android/native_window_jni.h> |
+#include <android_native_app_glue.h> |
djsollen
2016/05/06 18:45:26
we should not need this include.
liyuqian
2016/05/06 20:42:30
This is needed for LOOPER_ID_USER
djsollen
2016/05/09 13:29:44
you don't need LOOPER_ID_USER as that was somethin
liyuqian
2016/05/09 14:27:27
Done.
|
+ |
+#include "../Application.h" |
+#include "SkTypes.h" |
+#include "SkUtils.h" |
+#include "Window_android.h" |
+ |
+namespace sk_app { |
+ |
+static const int LOOPER_ID_MESSAGEPIPE = LOOPER_ID_USER; |
+ |
+void* pthread_main(void* arg); |
+ |
+AppThread::AppThread() { |
+ nativeWindow = nullptr; |
+ pthread_create(&thread, nullptr, pthread_main, this); |
+} |
+ |
+AppThread::~AppThread() { |
+ if (window) { |
+ window->detach(); |
+ } |
+ if (nativeWindow) { |
+ ANativeWindow_release(this->nativeWindow); |
+ this->nativeWindow = nullptr; |
+ } |
+ if (app) { |
+ delete app; |
+ } |
+} |
+ |
+void AppThread::postMessage(const Message& message) { |
+ auto writeSize = write(pipes[1], &message, sizeof(message)); |
+ SkASSERT(writeSize == sizeof(message)); |
+} |
+ |
+void AppThread::readMessage(Message* message) { |
+ auto readSize = read(pipes[0], message, sizeof(Message)); |
+ SkASSERT(readSize == sizeof(Message)); |
+} |
+ |
+static int message_callback(int fd, int events, void* data) { |
+ auto appThread = (AppThread*)data; |
+ Message message; |
+ appThread->readMessage(&message); |
+ SkDebugf("message_callback %d", message.type); |
+ |
+ switch (message.type) { |
+ case kDestroyApp: { |
+ delete appThread; |
+ pthread_exit(nullptr); |
+ return 0; |
+ } |
+ case kSurfaceCreated: { |
+ auto window_android = (Window_android*)appThread->window; |
+ window_android->initDisplay(appThread->nativeWindow); |
+ window_android->paintIfNeeded(); |
+ break; |
+ } |
+ case kSurfaceChanged: { |
+ int width = ANativeWindow_getWidth(appThread->nativeWindow); |
+ int height = ANativeWindow_getHeight(appThread->nativeWindow); |
+ appThread->window->onResize(width, height); |
+ auto window_android = (Window_android*)appThread->window; |
+ window_android->setContentRect(0, 0, width, height); |
+ window_android->paintIfNeeded(); |
+ break; |
+ } |
+ default: { |
+ // do nothing |
+ } |
+ } |
+ |
+ return 1; // continue receiving callbacks |
+} |
+ |
+void* pthread_main(void* arg) { |
+ SkDebugf("pthread_main begins"); |
+ |
+ auto appThread = (AppThread*)arg; |
+ |
+ ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); |
+ pipe(appThread->pipes); |
+ ALooper_addFd(looper, appThread->pipes[0], LOOPER_ID_MESSAGEPIPE, ALOOPER_EVENT_INPUT, |
+ message_callback, appThread); |
+ |
+ int ident; |
+ int events; |
+ struct android_poll_source* source; |
+ |
+ appThread->app = Application::Create(0, nullptr, appThread); |
+ |
+ while ((ident = ALooper_pollAll(-1, nullptr, &events, (void**)&source)) >= 0) { |
+ SkDebugf("ALooper_pollAll ident=%d", ident); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+extern "C" // extern "C" is needed for JNI (although the method itself is in C++) |
+ JNIEXPORT jlong JNICALL |
+ Java_org_skia_viewer_ViewerApplication_createNativeApp(JNIEnv* env, jobject activity) { |
+ AppThread* appThread = new AppThread; |
+ return (jlong)((size_t)appThread); |
+} |
+ |
+extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerApplication_destroyNativeApp( |
+ JNIEnv* env, jobject activity, jlong handle) { |
+ auto appThread = (AppThread*)handle; |
+ Message message(kDestroyApp); |
+ appThread->postMessage(message); |
+ pthread_join(appThread->thread, nullptr); |
+} |
+ |
+extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_MainActivity_onSurfaceCreated( |
+ JNIEnv* env, jobject activity, jlong handle, jobject surface) { |
+ auto appThread = (AppThread*)handle; |
+ |
+ SkASSERT(!appThread->nativeWindow); |
+ ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env, surface); |
+ appThread->nativeWindow = nativeWindow; |
+ |
+ Message message(kSurfaceCreated); |
+ appThread->postMessage(message); |
+} |
+ |
+extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_MainActivity_onSurfaceChanged( |
+ JNIEnv* env, jobject activity, jlong handle, jobject surface) { |
+ auto appThread = (AppThread*)handle; |
+ |
+ ANativeWindow* nativeWindow = ANativeWindow_fromSurface(env, surface); |
+ if (nativeWindow != appThread->nativeWindow) { |
+ ANativeWindow_release(appThread->nativeWindow); |
+ appThread->nativeWindow = nativeWindow; |
+ } |
+ |
+ Message message(kSurfaceChanged); |
+ appThread->postMessage(message); |
+} |
+ |
+extern "C" JNIEXPORT void JNICALL |
+Java_org_skia_viewer_MainActivity_onSurfaceDestroyed(JNIEnv* env, jobject activity, jlong handle) { |
+ auto appThread = (AppThread*)handle; |
+ |
+ if (appThread->nativeWindow) { |
+ ANativeWindow_release(appThread->nativeWindow); |
+ appThread->nativeWindow = nullptr; |
+ } |
+ |
+ Message message(kSurfaceDestroyed); |
+ appThread->postMessage(message); |
+} |
+ |
+} // namespace sk_app |