From 796c5bb4655a511553970e111c96d90963fb9ae4 Mon Sep 17 00:00:00 2001 From: liyuqian Date: Mon, 9 May 2016 08:49:29 -0700 Subject: Initial commit of our new Android app to demo Skia. Currently, there's only a simple Activity with a title bar and a surface view that connects with Skia viewer native application. Before integrating user action events, I want to make sure that the design and implementation so far are good. Note that the old NativeApplication-based Activity (ViewerActivity) is still there for reference and test purposes. It will be removed eventually. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1952323004 Review-Url: https://codereview.chromium.org/1952323004 --- .../viewer/sk_app/android/surface_glue_android.cpp | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 tools/viewer/sk_app/android/surface_glue_android.cpp (limited to '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 0000000000..b1d0029a10 --- /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 +#include +#include +#include + +#include +#include + +#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 -- cgit v1.2.3