Index: tools/vulkan/android/Window_android.cpp |
diff --git a/tools/vulkan/android/Window_android.cpp b/tools/vulkan/android/Window_android.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fb87a3f606b206bcbfd8e06507736317b2be3881 |
--- /dev/null |
+++ b/tools/vulkan/android/Window_android.cpp |
@@ -0,0 +1,179 @@ |
+/* |
+* 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 "Window_android.h" |
+ |
+#include "VulkanTestContext_android.h" |
+ |
+Window* Window::CreateNativeWindow(void* platformData) { |
+ Window_android* window = new Window_android(); |
+ if (!window->init((android_app*)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; |
+ return true; |
+} |
+ |
+void Window_android::setTitle(const char* title) { |
+ //todo |
+ SkDebugf("Title: %s", title); |
+} |
+ |
+bool Window_android::attach(BackEndType attachType, int msaaSampleCount, AttachmentInfo*) { |
+ if (kVulkan_BackendType != attachType) { |
+ return false; |
+ } |
+ |
+ mSampleCount = msaaSampleCount; |
+ |
+ // We delay the creation of fTestContext until Android informs us that |
+ // the native window is ready to use. |
+ return true; |
+} |
+ |
+void Window_android::initDisplay(ANativeWindow* window) { |
+ SkASSERT(window); |
+ ContextPlatformData_android platformData; |
+ platformData.fNativeWindow = window; |
+ fTestContext = VulkanTestContext::Create((void*)&platformData, mSampleCount); |
+} |
+ |
+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)); |
+ } |
+} |
+ |
+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; |
+} |
+ |
+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; |
+} |