Chromium Code Reviews| 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 |