| 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;
 | 
| +}
 | 
| 
 |