| 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..b1d0029a108759588e21351f7fe868e078dc1151
|
| --- /dev/null
|
| +++ b/tools/viewer/sk_app/android/surface_glue_android.cpp
|
| @@ -0,0 +1,174 @@
|
| +/*
|
| +* 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/looper.h>
|
| +#include <android/native_window_jni.h>
|
| +
|
| +#include "../Application.h"
|
| +#include "SkTypes.h"
|
| +#include "SkUtils.h"
|
| +#include "Window_android.h"
|
| +
|
| +namespace sk_app {
|
| +
|
| +static const int LOOPER_ID_MESSAGEPIPE = 1;
|
| +
|
| +void* pthread_main(void* arg);
|
| +
|
| +SkiaAndroidApp::SkiaAndroidApp() {
|
| + fNativeWindow = nullptr;
|
| + pthread_create(&fThread, nullptr, pthread_main, this);
|
| +}
|
| +
|
| +SkiaAndroidApp::~SkiaAndroidApp() {
|
| + if (fWindow) {
|
| + fWindow->detach();
|
| + }
|
| + if (fNativeWindow) {
|
| + ANativeWindow_release(fNativeWindow);
|
| + fNativeWindow = nullptr;
|
| + }
|
| + if (fApp) {
|
| + delete fApp;
|
| + }
|
| +}
|
| +
|
| +void SkiaAndroidApp::paintIfNeeded() {
|
| + if (fNativeWindow && fWindow) {
|
| + fWindow->onPaint();
|
| + }
|
| +}
|
| +
|
| +void SkiaAndroidApp::postMessage(const Message& message) {
|
| + auto writeSize = write(fPipes[1], &message, sizeof(message));
|
| + SkASSERT(writeSize == sizeof(message));
|
| +}
|
| +
|
| +void SkiaAndroidApp::readMessage(Message* message) {
|
| + auto readSize = read(fPipes[0], message, sizeof(Message));
|
| + SkASSERT(readSize == sizeof(Message));
|
| +}
|
| +
|
| +static int message_callback(int fd, int events, void* data) {
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)data;
|
| + Message message;
|
| + skiaAndroidApp->readMessage(&message);
|
| + SkDebugf("message_callback %d", message.fType);
|
| + SkASSERT(message.fType != kUndefined);
|
| +
|
| + switch (message.fType) {
|
| + case kDestroyApp: {
|
| + delete skiaAndroidApp;
|
| + pthread_exit(nullptr);
|
| + return 0;
|
| + }
|
| + case kContentInvalidated: {
|
| + skiaAndroidApp->paintIfNeeded();
|
| + break;
|
| + }
|
| + case kSurfaceCreated: {
|
| + SkASSERT(!skiaAndroidApp->fNativeWindow && message.fNativeWindow);
|
| + skiaAndroidApp->fNativeWindow = message.fNativeWindow;
|
| + auto window_android = (Window_android*)skiaAndroidApp->fWindow;
|
| + window_android->initDisplay(skiaAndroidApp->fNativeWindow);
|
| + skiaAndroidApp->paintIfNeeded();
|
| + break;
|
| + }
|
| + case kSurfaceChanged: {
|
| + SkASSERT(message.fNativeWindow == skiaAndroidApp->fNativeWindow &&
|
| + message.fNativeWindow);
|
| + int width = ANativeWindow_getWidth(skiaAndroidApp->fNativeWindow);
|
| + int height = ANativeWindow_getHeight(skiaAndroidApp->fNativeWindow);
|
| + skiaAndroidApp->fWindow->onResize(width, height);
|
| + auto window_android = (Window_android*)skiaAndroidApp->fWindow;
|
| + window_android->setContentRect(0, 0, width, height);
|
| + skiaAndroidApp->paintIfNeeded();
|
| + break;
|
| + }
|
| + case kSurfaceDestroyed: {
|
| + if (skiaAndroidApp->fNativeWindow) {
|
| + auto window_android = (Window_android*)skiaAndroidApp->fWindow;
|
| + window_android->onDisplayDestroyed();
|
| + ANativeWindow_release(skiaAndroidApp->fNativeWindow);
|
| + skiaAndroidApp->fNativeWindow = nullptr;
|
| + }
|
| + break;
|
| + }
|
| + default: {
|
| + // do nothing
|
| + }
|
| + }
|
| +
|
| + return 1; // continue receiving callbacks
|
| +}
|
| +
|
| +void* pthread_main(void* arg) {
|
| + SkDebugf("pthread_main begins");
|
| +
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)arg;
|
| +
|
| + ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
| + pipe(skiaAndroidApp->fPipes);
|
| + ALooper_addFd(looper, skiaAndroidApp->fPipes[0], LOOPER_ID_MESSAGEPIPE, ALOOPER_EVENT_INPUT,
|
| + message_callback, skiaAndroidApp);
|
| +
|
| + int ident;
|
| + int events;
|
| + struct android_poll_source* source;
|
| +
|
| + skiaAndroidApp->fApp = Application::Create(0, nullptr, skiaAndroidApp);
|
| +
|
| + 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) {
|
| + SkiaAndroidApp* skiaAndroidApp = new SkiaAndroidApp;
|
| + return (jlong)((size_t)skiaAndroidApp);
|
| +}
|
| +
|
| +extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerApplication_destroyNativeApp(
|
| + JNIEnv* env, jobject activity, jlong handle) {
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)handle;
|
| + skiaAndroidApp->postMessage(Message(kDestroyApp));
|
| +}
|
| +
|
| +extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onSurfaceCreated(
|
| + JNIEnv* env, jobject activity, jlong handle, jobject surface) {
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)handle;
|
| + Message message(kSurfaceCreated);
|
| + message.fNativeWindow = ANativeWindow_fromSurface(env, surface);
|
| + skiaAndroidApp->postMessage(message);
|
| +}
|
| +
|
| +extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onSurfaceChanged(
|
| + JNIEnv* env, jobject activity, jlong handle, jobject surface) {
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)handle;
|
| + Message message(kSurfaceChanged);
|
| + message.fNativeWindow = ANativeWindow_fromSurface(env, surface);
|
| + skiaAndroidApp->postMessage(message);
|
| +}
|
| +
|
| +extern "C" JNIEXPORT void JNICALL Java_org_skia_viewer_ViewerActivity_onSurfaceDestroyed(
|
| + JNIEnv* env, jobject activity, jlong handle) {
|
| + auto skiaAndroidApp = (SkiaAndroidApp*)handle;
|
| + skiaAndroidApp->postMessage(Message(kSurfaceDestroyed));
|
| +}
|
| +
|
| +} // namespace sk_app
|
|
|