VulkanViewer on Android
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1903253003 Review URL: https://codereview.chromium.org/1903253003
This commit is contained in:
parent
d37fe76b51
commit
12d62a7d51
1
DEPS
1
DEPS
@ -53,6 +53,7 @@ deps = {
|
||||
"third_party/externals/shaderc2/third_party/googletest" : "https://github.com/google/googletest.git@d225acc90bc3a8c420a9bcd1f033033c1ccd7fe0",
|
||||
"third_party/externals/shaderc2/third_party/glslang" : "https://github.com/google/glslang.git@e1cd410d9c03a24c00c570c91a99cad88bb475d1",
|
||||
"third_party/externals/shaderc2/third_party/spirv-tools" : "https://github.com/KhronosGroup/SPIRV-Tools.git@009c4358b5a1c93203166b3ed60a548f63522e81",
|
||||
"third_party/externals/shaderc2/third_party/android-cmake" : "https://github.com/taka-no-me/android-cmake.git@556cc14296c226f753a3778d99d8b60778b7df4f",
|
||||
}
|
||||
|
||||
deps_os = {
|
||||
|
@ -59,6 +59,11 @@
|
||||
'android_system.gyp:VisualBench_APK',
|
||||
],
|
||||
}],
|
||||
[ 'skia_vulkan == 1', {
|
||||
'dependencies': [
|
||||
'android_system.gyp:VulkanViewer_APK',
|
||||
],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['skia_os == "ios"', {
|
||||
@ -79,7 +84,7 @@
|
||||
'skiaserve.gyp:skiaserve',
|
||||
],
|
||||
}],
|
||||
[ 'skia_vulkan == 0 or skia_os != "win"', {
|
||||
[ 'skia_vulkan == 0 or skia_os != "win" or skia_os != "android"', {
|
||||
'dependencies!': [
|
||||
'vulkanviewer.gyp:vulkanviewer',
|
||||
],
|
||||
|
@ -28,13 +28,14 @@
|
||||
'shaderc_project_type' : 'ninja',
|
||||
}],
|
||||
],
|
||||
'shaderc_out_path': '../out/<(CONFIGURATION_NAME)/shaderc_out_<(skia_arch_type)',
|
||||
'shaderc_out_path': '<(PRODUCT_DIR)/shaderc_out_<(skia_arch_type)',
|
||||
},
|
||||
# Export out of nested variables.
|
||||
'shaderc_build_configuration': '<(shaderc_build_configuration)',
|
||||
'shaderc_project_type': '<(shaderc_project_type)',
|
||||
'shaderc_out_path': '<(shaderc_out_path)',
|
||||
'shaderc_lib_name': '<(shaderc_lib_name)',
|
||||
'android_toolchain%': '',
|
||||
|
||||
# On Windows the library winds up inside a 'Debug' or 'Release' dir, not so
|
||||
# with ninja project build.
|
||||
@ -62,12 +63,12 @@
|
||||
'outputs': [
|
||||
'<(shaderc_lib_full_path)',
|
||||
],
|
||||
'action': ['python', '../tools/build_shaderc.py', '-s', '../third_party/externals/shaderc2', '-o', '<(shaderc_out_path)', '-a', '<(skia_arch_type)', '-t', '<(shaderc_build_configuration)', '-p', '<(shaderc_project_type)'],
|
||||
'action': ['python', '../tools/build_shaderc.py', '-s', '../third_party/externals/shaderc2', '-o', '<(shaderc_out_path)', '-a', '<(skia_arch_type)', '-t', '<(shaderc_build_configuration)', '-p', '<(shaderc_project_type)', '-c', '<(android_toolchain)'],
|
||||
},
|
||||
],
|
||||
'copies': [
|
||||
{
|
||||
'destination': '../out/<(CONFIGURATION_NAME)',
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': ['<(shaderc_lib_full_path)'],
|
||||
},
|
||||
],
|
||||
|
@ -42,6 +42,27 @@
|
||||
'tools.gyp:timer',
|
||||
'tools.gyp:url_data_manager',
|
||||
],
|
||||
'conditions' : [
|
||||
[ 'skia_os == "android"', {
|
||||
'dependencies': [
|
||||
'android_deps.gyp:Android_EntryPoint',
|
||||
'android_deps.gyp:native_app_glue',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-landroid',
|
||||
],
|
||||
},
|
||||
}],
|
||||
['skia_os != "android"', {
|
||||
'sources/': [ ['exclude', '_android.(h|cpp)$'],
|
||||
],
|
||||
}],
|
||||
['skia_os != "win"', {
|
||||
'sources/': [ ['exclude', '_win.(h|cpp)$'],
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
@ -2,3 +2,4 @@ include ':sample_app'
|
||||
include ':visualbench'
|
||||
include ':visualbenchsdl'
|
||||
include ':canvasproof'
|
||||
include ':vulkanviewer'
|
||||
|
37
platform_tools/android/apps/vulkanviewer/build.gradle
Normal file
37
platform_tools/android/apps/vulkanviewer/build.gradle
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
apply plugin: 'com.android.application'
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "22.0.1"
|
||||
defaultConfig {
|
||||
applicationId "org.skia.vulkanviewer"
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 19
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call
|
||||
sourceSets.main.jniLibs.srcDir "src/main/libs"
|
||||
productFlavors { arm {}; arm64 {}; x86 {}; x86_64 {}; mips {}; mips64 {}; }
|
||||
applicationVariants.all{ variant ->
|
||||
def buildNativeLib = task("${variant.name}_NativeLib", type:Exec) {
|
||||
workingDir '../../../..' // top-level skia directory
|
||||
commandLine constructBuildCommand(variant, "CopyVulkanViewerDeps").split()
|
||||
environment PATH: getPathWithDepotTools()
|
||||
environment ANDROID_SDK_ROOT: getSDKPath()
|
||||
}
|
||||
buildNativeLib.onlyIf { !project.hasProperty("suppressNativeBuild") }
|
||||
TaskCollection<Task> assembleTask
|
||||
assembleTask = project.tasks.matching {
|
||||
it.name.contains("assemble") &&
|
||||
it.name.toLowerCase().endsWith(variant.name.toLowerCase())
|
||||
}
|
||||
assembleTask.getAt(0).dependsOn buildNativeLib
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- BEGIN_INCLUDE(manifest) -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.skia.vulkanviewer"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:label="VulkanViewer">
|
||||
|
||||
<activity android:name=".VulkanViewerActivity"
|
||||
android:label="VulkanViewer"
|
||||
android:screenOrientation="portrait"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
<meta-data android:name="android.app.lib_name"
|
||||
android:value="vulkanviewer" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
<!-- END_INCLUDE(manifest) -->
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package com.skia.vulkanviewer;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
public class VulkanViewerActivity extends android.app.NativeActivity {
|
||||
static {
|
||||
System.loadLibrary("skia_android");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
ActionBar ab = this.getActionBar();
|
||||
ab.hide();
|
||||
}
|
||||
}
|
@ -38,6 +38,8 @@ while (( "$#" )); do
|
||||
LOGCAT=1
|
||||
elif [[ "$1" == "--verbose" ]]; then
|
||||
VERBOSE="true"
|
||||
elif [[ "$1" == "--vulkan" ]]; then
|
||||
SKIA_VULKAN="true"
|
||||
else
|
||||
APP_ARGS=("${APP_ARGS[@]}" "${1}")
|
||||
fi
|
||||
@ -48,6 +50,10 @@ if [ "$USE_CLANG" == "true" ]; then
|
||||
export GYP_DEFINES="skia_clang_build=1 $GYP_DEFINES"
|
||||
fi
|
||||
|
||||
if [ "$SKIA_VULKAN" == "true" ]; then
|
||||
export GYP_DEFINES="skia_vulkan=1 $GYP_DEFINES"
|
||||
fi
|
||||
|
||||
function verbose {
|
||||
if [[ -n $VERBOSE ]]; then
|
||||
echo $@
|
||||
@ -167,7 +173,7 @@ setup_device() {
|
||||
source $SCRIPT_DIR/utils/setup_toolchain.sh
|
||||
fi
|
||||
|
||||
DEFINES="${DEFINES} android_toolchain=${TOOLCHAIN_TYPE}"
|
||||
DEFINES="${DEFINES} android_toolchain=${ANDROID_TOOLCHAIN}"
|
||||
DEFINES="${DEFINES} android_buildtype=${BUILDTYPE}"
|
||||
exportVar GYP_DEFINES "$DEFINES $GYP_DEFINES"
|
||||
|
||||
|
@ -42,6 +42,10 @@ function default_toolchain() {
|
||||
else
|
||||
API=14 # Android 4.0
|
||||
fi
|
||||
|
||||
if [ "$SKIA_VULKAN" == "true" ]; then
|
||||
API=24 # Android N Preview
|
||||
fi
|
||||
|
||||
TOOLCHAIN=$ANDROID_ARCH-$NDK-$API
|
||||
HOST=`uname | tr '[A-Z]' '[a-z]'`
|
||||
|
@ -45,7 +45,10 @@
|
||||
}],
|
||||
],
|
||||
},
|
||||
'includes' : [ 'canvasproof.gypi', ],
|
||||
'includes' : [
|
||||
'canvasproof.gypi',
|
||||
'vulkanviewer.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'CopySampleAppDeps',
|
||||
|
65
platform_tools/android/gyp/vulkanviewer.gypi
Normal file
65
platform_tools/android/gyp/vulkanviewer.gypi
Normal file
@ -0,0 +1,65 @@
|
||||
# Copyright 2015 Google Inc.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'CopyVulkanViewerDeps',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'skia_lib.gyp:skia_lib',
|
||||
'vulkanviewer.gyp:vulkanviewer',
|
||||
],
|
||||
'copies': [
|
||||
{
|
||||
'destination': '<(android_base)/apps/vulkanviewer/src/main/libs/<(android_arch)',
|
||||
'conditions': [
|
||||
[ 'skia_shared_lib', {
|
||||
'files': [
|
||||
'<(SHARED_LIB_DIR)/libskia_android.so',
|
||||
'<(SHARED_LIB_DIR)/libvulkanviewer.so',
|
||||
]}, {
|
||||
'files': [
|
||||
'<(SHARED_LIB_DIR)/libvulkanviewer.so',
|
||||
]}
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'VulkanViewer_APK',
|
||||
'type': 'none',
|
||||
'dependencies': [ 'CopyVulkanViewerDeps', ],
|
||||
'actions': [
|
||||
{
|
||||
'action_name': 'SkiaVulkanViewer_apk',
|
||||
'inputs': [
|
||||
'<(android_base)/apps/vulkanviewer/src/main/AndroidManifest.xml',
|
||||
'<(android_base)/apps/vulkanviewer/src/main/java/com/skia/vulkanviewer/VulkanViewerActivity.java',
|
||||
'<(android_base)/apps/vulkanviewer/src/main/libs/<(android_arch)/libvulkanviewer.so',
|
||||
|
||||
],
|
||||
'conditions': [
|
||||
[ 'skia_shared_lib', {
|
||||
'inputs': [
|
||||
'<(android_base)/apps/vulkanviewer/src/main/libs/<(android_arch)/libskia_android.so',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'outputs': [
|
||||
'../apps/vulkanviewer/build/outputs/apk/',
|
||||
],
|
||||
'action': [
|
||||
'<(android_base)/apps/gradlew',
|
||||
':vulkanviewer:assemble<(android_variant)Debug',
|
||||
'-p<(android_base)/apps/vulkanviewer',
|
||||
'-PsuppressNativeBuild',
|
||||
'--daemon',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
@ -419,6 +419,13 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
|
||||
android_app_set_input((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) {
|
||||
struct android_app* android_app = (struct android_app*)activity->instance;
|
||||
LOGV("OnContentRectChanged: %p\n", activity);
|
||||
android_app->contentRect = *rect;
|
||||
android_app_write_cmd(android_app, APP_CMD_CONTENT_RECT_CHANGED);
|
||||
}
|
||||
|
||||
void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||
void* savedState, size_t savedStateSize) {
|
||||
LOGV("Creating: %p\n", activity);
|
||||
@ -435,6 +442,7 @@ void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
activity->callbacks->onContentRectChanged = onContentRectChanged;
|
||||
|
||||
activity->instance = android_app_create(activity, savedState, savedStateSize);
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ def main():
|
||||
'Directory for cmake build')
|
||||
parser.add_argument('-p', '--project_type', required=True, help=
|
||||
'Project type to use. Must be "ninja", "MSVS2013", or "MSVS2015"')
|
||||
parser.add_argument('-c', '--android_toolchain', required=False, help=
|
||||
'Location of standalone android toolchain to use for crosscompiling')
|
||||
args = parser.parse_args()
|
||||
|
||||
args.src_dir = os.path.abspath(args.src_dir)
|
||||
@ -44,12 +46,9 @@ def main():
|
||||
else:
|
||||
args.exit('Invalid build type: ' + args.build_type);
|
||||
|
||||
if args.arch_type == 'x86':
|
||||
vs_arch = ''
|
||||
elif args.arch_type == 'x86_64':
|
||||
vs_arch = ''
|
||||
if args.arch_type == 'x86_64':
|
||||
vs_arch = ' Win64'
|
||||
else:
|
||||
sys.exit('Invalid arch type: ' + args.arch_type);
|
||||
|
||||
if args.project_type == 'ninja':
|
||||
generator = 'Ninja'
|
||||
@ -70,9 +69,17 @@ def main():
|
||||
|
||||
try:
|
||||
build_type_arg='-DCMAKE_BUILD_TYPE=' + args.build_type
|
||||
subprocess.check_call(['cmake', '-G', generator,
|
||||
'-DSPIRV_SKIP_EXECUTABLES=ON', '-DSHADERC_ENABLE_SHARED_CRT=ON',
|
||||
args.src_dir, build_type_arg], cwd=args.output_dir)
|
||||
cmake_cmd = ['cmake', '-G', generator,
|
||||
'-DSPIRV_SKIP_EXECUTABLES=ON',
|
||||
'-DSHADERC_ENABLE_SHARED_CRT=ON']
|
||||
if args.android_toolchain and args.android_toolchain.strip() :
|
||||
cmake_cmd.append('-DCMAKE_TOOLCHAIN_FILE=' + args.src_dir +\
|
||||
'/third_party/android-cmake/android.toolchain.cmake')
|
||||
cmake_cmd.append('-DANDROID_TOOLCHAIN_NAME=standalone-clang')
|
||||
cmake_cmd.append('-DANDROID_STANDALONE_TOOLCHAIN=' +\
|
||||
os.path.abspath(args.android_toolchain))
|
||||
cmake_cmd.extend([build_type_arg, args.src_dir])
|
||||
subprocess.check_call(cmake_cmd, cwd=args.output_dir)
|
||||
except subprocess.CalledProcessError as error:
|
||||
sys.exit('Error (ret code: {code}) calling "{cmd}" in {dir}'.format(
|
||||
code = error.returncode, cmd = error.cmd, dir = args.src_dir))
|
||||
@ -86,4 +93,3 @@ def main():
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define Window_DEFINED
|
||||
|
||||
#include "SkTypes.h"
|
||||
#include "SkRect.h"
|
||||
|
||||
class SkCanvas;
|
||||
class VulkanTestContext;
|
||||
@ -23,6 +24,10 @@ public:
|
||||
virtual void show() = 0;
|
||||
virtual void inval() = 0;
|
||||
|
||||
virtual bool scaleContentToFit() const { return false; }
|
||||
virtual bool supportsContentRect() const { return false; }
|
||||
virtual SkRect getContentRect() { return SkRect::MakeEmpty(); }
|
||||
|
||||
struct AttachmentInfo {
|
||||
int fSampleCount;
|
||||
int fStencilBits;
|
||||
|
37
tools/vulkan/android/VulkanTestContext_android.cpp
Normal file
37
tools/vulkan/android/VulkanTestContext_android.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "VulkanTestContext_android.h"
|
||||
|
||||
#include "vk/GrVkInterface.h"
|
||||
#include "../../src/gpu/vk/GrVkUtil.h"
|
||||
|
||||
VkSurfaceKHR VulkanTestContext::createVkSurface(void* platformData) {
|
||||
// need better error handling here
|
||||
SkASSERT(platformData);
|
||||
ContextPlatformData_android* androidPlatformData =
|
||||
reinterpret_cast<ContextPlatformData_android*>(platformData);
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
|
||||
memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
|
||||
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
|
||||
surfaceCreateInfo.pNext = nullptr;
|
||||
surfaceCreateInfo.flags = 0;
|
||||
surfaceCreateInfo.window = androidPlatformData->fNativeWindow;
|
||||
|
||||
VkResult res = GR_VK_CALL(fBackendContext->fInterface,
|
||||
CreateAndroidSurfaceKHR(fBackendContext->fInstance,
|
||||
&surfaceCreateInfo,
|
||||
nullptr, &surface));
|
||||
return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
bool VulkanTestContext::canPresent(uint32_t queueFamilyIndex) {
|
||||
return true;
|
||||
}
|
23
tools/vulkan/android/VulkanTestContext_android.h
Normal file
23
tools/vulkan/android/VulkanTestContext_android.h
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
/*
|
||||
* 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 VULKANTESTCONTEXT_ANDROID_DEFINED
|
||||
#define VULKANTESTCONTEXT_ANDROID_DEFINED
|
||||
|
||||
#ifdef SK_VULKAN
|
||||
|
||||
#include "../VulkanTestContext.h"
|
||||
|
||||
struct ANativeWindow;
|
||||
|
||||
struct ContextPlatformData_android {
|
||||
ANativeWindow* fNativeWindow;
|
||||
};
|
||||
|
||||
#endif // SK_VULKAN
|
||||
|
||||
#endif
|
179
tools/vulkan/android/Window_android.cpp
Normal file
179
tools/vulkan/android/Window_android.cpp
Normal file
@ -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;
|
||||
}
|
48
tools/vulkan/android/Window_android.h
Normal file
48
tools/vulkan/android/Window_android.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 Window_android_DEFINED
|
||||
#define Window_android_DEFINED
|
||||
|
||||
#include "../Window.h"
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
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);
|
||||
void initDisplay(ANativeWindow* window);
|
||||
|
||||
void setTitle(const char*) override;
|
||||
void show() override {}
|
||||
|
||||
bool attach(BackEndType attachType, int msaaSampleCount, AttachmentInfo*) 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); }
|
||||
|
||||
private:
|
||||
android_app* mApp = nullptr;
|
||||
SkRect mContentRect;
|
||||
int mSampleCount = 0;
|
||||
};
|
||||
|
||||
#endif
|
67
tools/vulkan/android/main_android.cpp
Normal file
67
tools/vulkan/android/main_android.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 <jni.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include "../Application.h"
|
||||
#include "Timer.h"
|
||||
|
||||
static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
|
||||
|
||||
/**
|
||||
* This is the main entry point of a native application that is using
|
||||
* android_native_app_glue. It runs in its own thread, with its own
|
||||
* event loop for receiving input events and doing other things.
|
||||
*/
|
||||
void android_main(struct android_app* state) {
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
static const char* gCmdLine[] = {
|
||||
"vulkanviewer",
|
||||
"--skps",
|
||||
"/data/local/tmp/skp",
|
||||
};
|
||||
|
||||
std::unique_ptr<Application> vkApp(Application::Create(SK_ARRAY_COUNT(gCmdLine),
|
||||
const_cast<char**>(gCmdLine),
|
||||
state));
|
||||
|
||||
double currentTime = 0.0;
|
||||
double previousTime = 0.0;
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
while (1) {
|
||||
// Read all pending events.
|
||||
int ident;
|
||||
int events;
|
||||
struct android_poll_source* source;
|
||||
|
||||
// block forever waiting for events.
|
||||
while ((ident=ALooper_pollAll(-1, NULL, &events,
|
||||
(void**)&source)) >= 0) {
|
||||
|
||||
// Process this event.
|
||||
if (source != NULL) {
|
||||
source->process(state, source);
|
||||
}
|
||||
|
||||
// Check if we are exiting.
|
||||
if (state->destroyRequested != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
previousTime = currentTime;
|
||||
currentTime = now_ms();
|
||||
vkApp->onIdle(currentTime - previousTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
//END_INCLUDE(all)
|
@ -16,6 +16,8 @@ public:
|
||||
GMSlide(skiagm::GM* gm);
|
||||
~GMSlide() override;
|
||||
|
||||
SkISize getDimensions() const override { return fGM->getISize(); }
|
||||
|
||||
void draw(SkCanvas* canvas) override;
|
||||
bool animate(const SkAnimTimer&) override;
|
||||
|
||||
|
@ -16,6 +16,8 @@ public:
|
||||
SKPSlide(const SkString& name, const SkString& path);
|
||||
~SKPSlide() override;
|
||||
|
||||
SkISize getDimensions() const override { return fCullRect.size(); }
|
||||
|
||||
void draw(SkCanvas* canvas) override;
|
||||
void load() override;
|
||||
void unload() override;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define Slide_DEFINED
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkSize.h"
|
||||
#include "SkString.h"
|
||||
|
||||
class SkCanvas;
|
||||
@ -18,6 +19,8 @@ class Slide : public SkRefCnt {
|
||||
public:
|
||||
virtual ~Slide() {}
|
||||
|
||||
virtual SkISize getDimensions() const = 0;
|
||||
|
||||
virtual void draw(SkCanvas* canvas) = 0;
|
||||
virtual bool animate(const SkAnimTimer&) { return false; }
|
||||
virtual void load() {}
|
||||
|
@ -81,10 +81,12 @@ VulkanViewer::VulkanViewer(int argc, char** argv, void* platformData)
|
||||
// set up slides
|
||||
this->initSlides();
|
||||
|
||||
fAnimTimer.run();
|
||||
|
||||
// set up first frame
|
||||
fCurrentSlide = 0;
|
||||
setupCurrentSlide(-1);
|
||||
fLocalMatrix.reset();
|
||||
updateMatrix();
|
||||
|
||||
fWindow->show();
|
||||
}
|
||||
@ -254,10 +256,24 @@ bool VulkanViewer::onChar(SkUnichar c, uint32_t modifiers) {
|
||||
|
||||
void VulkanViewer::onPaint(SkCanvas* canvas) {
|
||||
|
||||
canvas->clear(SK_ColorWHITE);
|
||||
|
||||
int count = canvas->save();
|
||||
canvas->setMatrix(fLocalMatrix);
|
||||
|
||||
if (fWindow->supportsContentRect()) {
|
||||
SkRect contentRect = fWindow->getContentRect();
|
||||
canvas->clipRect(contentRect);
|
||||
canvas->translate(contentRect.fLeft, contentRect.fTop);
|
||||
}
|
||||
|
||||
canvas->clear(SK_ColorWHITE);
|
||||
if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
|
||||
const SkRect contentRect = fWindow->getContentRect();
|
||||
const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
|
||||
const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
|
||||
SkMatrix matrix;
|
||||
matrix.setRectToRect(slideBounds, contentRect, SkMatrix::kCenter_ScaleToFit);
|
||||
canvas->concat(matrix);
|
||||
}
|
||||
canvas->concat(fLocalMatrix);
|
||||
|
||||
fSlides[fCurrentSlide]->draw(canvas);
|
||||
canvas->restoreToCount(count);
|
||||
@ -282,6 +298,12 @@ void VulkanViewer::drawStats(SkCanvas* canvas) {
|
||||
SkPaint paint;
|
||||
canvas->save();
|
||||
|
||||
if (fWindow->supportsContentRect()) {
|
||||
SkRect contentRect = fWindow->getContentRect();
|
||||
canvas->clipRect(contentRect);
|
||||
canvas->translate(contentRect.fLeft, contentRect.fTop);
|
||||
}
|
||||
|
||||
canvas->clipRect(rect);
|
||||
paint.setColor(SK_ColorBLACK);
|
||||
canvas->drawRect(rect, paint);
|
||||
|
Loading…
Reference in New Issue
Block a user