aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/viewer/sk_app
diff options
context:
space:
mode:
Diffstat (limited to 'tools/viewer/sk_app')
-rw-r--r--tools/viewer/sk_app/VulkanWindowContext.h4
-rw-r--r--tools/viewer/sk_app/android/Window_android.cpp143
-rw-r--r--tools/viewer/sk_app/android/Window_android.h23
-rw-r--r--tools/viewer/sk_app/android/surface_glue_android.cpp174
-rw-r--r--tools/viewer/sk_app/android/surface_glue_android.h55
5 files changed, 250 insertions, 149 deletions
diff --git a/tools/viewer/sk_app/VulkanWindowContext.h b/tools/viewer/sk_app/VulkanWindowContext.h
index e186881565..ec80a3251d 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.h
+++ b/tools/viewer/sk_app/VulkanWindowContext.h
@@ -46,8 +46,8 @@ public:
this->createSwapchain(w, h, fDisplayParams);
}
- const DisplayParams& getDisplayParams() { return fDisplayParams; }
- void setDisplayParams(const DisplayParams& params) {
+ const DisplayParams& getDisplayParams() override { return fDisplayParams; }
+ void setDisplayParams(const DisplayParams& params) override {
this->createSwapchain(fWidth, fHeight, params);
}
diff --git a/tools/viewer/sk_app/android/Window_android.cpp b/tools/viewer/sk_app/android/Window_android.cpp
index 9def29fbf4..09e7ef14a7 100644
--- a/tools/viewer/sk_app/android/Window_android.cpp
+++ b/tools/viewer/sk_app/android/Window_android.cpp
@@ -13,22 +13,17 @@ namespace sk_app {
Window* Window::CreateNativeWindow(void* platformData) {
Window_android* window = new Window_android();
- if (!window->init((android_app*)platformData)) {
+ if (!window->init((SkiaAndroidApp*)platformData)) {
delete window;
return nullptr;
}
return window;
}
-static void handle_cmd(struct android_app* app, int32_t cmd);
-static int32_t handle_input(struct android_app* app, AInputEvent* event);
-
-bool Window_android::init(android_app* app) {
- SkASSERT(app);
- mApp = app;
- mApp->userData = this;
- mApp->onAppCmd = handle_cmd;
- mApp->onInputEvent = handle_input;
+bool Window_android::init(SkiaAndroidApp* skiaAndroidApp) {
+ SkASSERT(skiaAndroidApp);
+ fSkiaAndroidApp = skiaAndroidApp;
+ fSkiaAndroidApp->fWindow = this;
return true;
}
@@ -53,131 +48,15 @@ void Window_android::initDisplay(ANativeWindow* window) {
SkASSERT(window);
ContextPlatformData_android platformData;
platformData.fNativeWindow = window;
- fWindowContext = VulkanWindowContext::Create((void*)&platformData, mSampleCount, fSRGB);
-}
-
-static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
- if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
- SkDebugf("Failure writing android_app cmd: %s\n", strerror(errno));
- }
+ fWindowContext = VulkanWindowContext::Create((void*)&platformData, fDisplayParams);
+ fNativeWindowInitialized = true;
}
-void Window_android::inval() {
- android_app_write_cmd(mApp, APP_CMD_INVAL_WINDOW);
-}
-
-void Window_android::paintIfNeeded() {
- if (mApp->window || !mContentRect.isEmpty()) {
- this->onPaint();
- }
-}
-
-/**
- * Process the next main command.
- */
-static void handle_cmd(struct android_app* app, int32_t cmd) {
- Window_android* window = (Window_android*)app->userData;
- switch (cmd) {
- case APP_CMD_INIT_WINDOW:
- // The window is being shown, get it ready.
- SkASSERT(app->window);
- window->initDisplay(app->window);
- window->paintIfNeeded();
- break;
- case APP_CMD_WINDOW_RESIZED: {
- int width = ANativeWindow_getWidth(app->window);
- int height = ANativeWindow_getHeight(app->window);
- window->onResize(width, height);
- break;
- }
- case APP_CMD_CONTENT_RECT_CHANGED:
- window->setContentRect(app->contentRect.left, app->contentRect.top,
- app->contentRect.right, app->contentRect.bottom);
- window->paintIfNeeded();
- break;
- case APP_CMD_TERM_WINDOW:
- // The window is being hidden or closed, clean it up.
- window->detach();
- break;
- case APP_CMD_INVAL_WINDOW:
- window->paintIfNeeded();
- break;
- }
-}
-
-static Window::Key get_key(int32_t keycode) {
- static const struct {
- int32_t fAndroidKey;
- Window::Key fWindowKey;
- } gPair[] = {
- { AKEYCODE_BACK, Window::kBack_Key },
- { AKEYCODE_VOLUME_UP, Window::kLeft_Key },
- { AKEYCODE_VOLUME_DOWN, Window::kRight_Key }
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fAndroidKey == keycode) {
- return gPair[i].fWindowKey;
- }
- }
- return Window::kNONE_Key;
+void Window_android::onDisplayDestroyed() {
+ fNativeWindowInitialized = false;
+ detach();
}
-static Window::InputState get_action(int32_t action) {
- static const struct {
- int32_t fAndroidAction;
- Window::InputState fInputState;
- } gPair[] = {
- { AKEY_STATE_DOWN, Window::kDown_InputState },
- { AKEY_STATE_UP, Window::kUp_InputState },
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fAndroidAction == action) {
- return gPair[i].fInputState;
- }
- }
- return Window::kMove_InputState;
-}
-
-static int32_t get_key_modifiers(AInputEvent* event) {
- static const struct {
- int32_t fAndroidState;
- int32_t fWindowModifier;
- } gPair[] = {
- { AMETA_SHIFT_ON, Window::kShift_ModifierKey },
- { AMETA_CTRL_ON, Window::kControl_ModifierKey },
- };
-
- int32_t metaState = AKeyEvent_getMetaState(event);
- int32_t modifiers = 0;
-
- if (AKeyEvent_getRepeatCount(event) == 0) {
- modifiers |= Window::kFirstPress_ModifierKey;
- }
-
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fAndroidState == metaState) {
- modifiers |= gPair[i].fWindowModifier;
- }
- }
- return modifiers;
-}
-
-/**
- * Process the next input event.
- */
-static int32_t handle_input(struct android_app* app, AInputEvent* event) {
- Window_android* window = (Window_android*)app->userData;
- switch(AInputEvent_getType(event)) {
- case AINPUT_EVENT_TYPE_MOTION:
- break;
- case AINPUT_EVENT_TYPE_KEY:
- Window::Key key = get_key(AKeyEvent_getKeyCode(event));
- Window::InputState state = get_action(AKeyEvent_getAction(event));
- int32_t mod = get_key_modifiers(event);
- window->onKey(key, state, mod);
- return true; // eat all key events
- }
- return 0;
-}
+void Window_android::inval() { fSkiaAndroidApp->postMessage(Message(kContentInvalidated)); }
} // namespace sk_app
diff --git a/tools/viewer/sk_app/android/Window_android.h b/tools/viewer/sk_app/android/Window_android.h
index b570615075..45e5bbe744 100644
--- a/tools/viewer/sk_app/android/Window_android.h
+++ b/tools/viewer/sk_app/android/Window_android.h
@@ -9,24 +9,18 @@
#define Window_android_DEFINED
#include "../Window.h"
-#include <android_native_app_glue.h>
+#include "surface_glue_android.h"
namespace sk_app {
-enum {
- /**
- * Leave plenty of space between this item and the ones defined in the glue layer
- */
- APP_CMD_INVAL_WINDOW = 64,
-};
-
class Window_android : public Window {
public:
Window_android() : Window() {}
~Window_android() override {}
- bool init(android_app* app_state);
+ bool init(SkiaAndroidApp* skiaAndroidApp);
void initDisplay(ANativeWindow* window);
+ void onDisplayDestroyed();
void setTitle(const char*) override;
void show() override {}
@@ -34,17 +28,16 @@ public:
bool attach(BackEndType attachType, const DisplayParams& params) override;
void inval() override;
- void paintIfNeeded();
-
bool scaleContentToFit() const override { return true; }
bool supportsContentRect() const override { return true; }
- SkRect getContentRect() override { return mContentRect; }
- void setContentRect(int l, int t, int r, int b) { mContentRect.set(l,t,r,b); }
+ SkRect getContentRect() override { return fContentRect; }
+ void setContentRect(int l, int t, int r, int b) { fContentRect.set(l,t,r,b); }
private:
- android_app* mApp = nullptr;
- SkRect mContentRect;
+ SkiaAndroidApp* fSkiaAndroidApp = nullptr;
+ SkRect fContentRect;
DisplayParams fDisplayParams;
+ bool fNativeWindowInitialized = false;
};
} // namespace sk_app
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 <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
diff --git a/tools/viewer/sk_app/android/surface_glue_android.h b/tools/viewer/sk_app/android/surface_glue_android.h
new file mode 100644
index 0000000000..aefe46208d
--- /dev/null
+++ b/tools/viewer/sk_app/android/surface_glue_android.h
@@ -0,0 +1,55 @@
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#ifndef surface_glue_android_DEFINED
+#define surface_glue_android_DEFINED
+
+#include <pthread.h>
+
+#include <android/native_window_jni.h>
+
+#include "../Application.h"
+#include "../Window.h"
+
+namespace sk_app {
+
+enum MessageType {
+ kUndefined,
+ kSurfaceCreated,
+ kSurfaceChanged,
+ kSurfaceDestroyed,
+ kDestroyApp,
+ kContentInvalidated
+};
+
+struct Message {
+ MessageType fType = kUndefined;
+ ANativeWindow* fNativeWindow = nullptr;
+
+ Message() {}
+ Message(MessageType t) : fType(t) {}
+};
+
+struct SkiaAndroidApp {
+ int fPipes[2]; // 0 is the read message pipe, 1 is the write message pipe
+ Application* fApp;
+ Window* fWindow;
+ ANativeWindow* fNativeWindow;
+
+ SkiaAndroidApp();
+ ~SkiaAndroidApp();
+ void postMessage(const Message& message);
+ void readMessage(Message* message);
+ void paintIfNeeded();
+
+private:
+ pthread_t fThread;
+};
+
+} // namespace sk_app
+
+#endif