'visualbench.gyp:visualbench',
'fuzz.gyp:fuzz',
'kilobench.gyp:kilobench',
- 'vulkanviewer.gyp:vulkanviewer',
+ 'viewer.gyp:viewer',
],
'conditions': [
[ 'skia_gpu == 0', {
'dependencies!': [
'visualbench.gyp:visualbench',
'kilobench.gyp:kilobench',
- 'vulkanviewer.gyp:vulkanviewer',
+ 'viewer.gyp:viewer',
]
}],
[ 'skia_os != "android" and skia_os != "linux"', {
}],
[ 'skia_vulkan == 1', {
'dependencies': [
- 'android_system.gyp:VulkanViewer_APK',
+ 'android_system.gyp:Viewer_APK',
],
}],
],
}],
[ 'skia_vulkan == 0 or (skia_os != "win" and skia_os != "android")', {
'dependencies!': [
- 'vulkanviewer.gyp:vulkanviewer',
+ 'viewer.gyp:viewer',
],
}],
[ 'skia_skip_gui',
--- /dev/null
+# Copyright 2016 Google Inc.
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# GYP file to build performance testbench.
+#
+{
+ 'includes': [
+ 'apptype_console.gypi',
+ ],
+ 'targets': [
+ {
+ 'target_name': 'viewer',
+ 'type': 'executable',
+ 'includes' : [
+ 'gmslides.gypi',
+ ],
+ 'include_dirs': [
+ '../bench',
+ '../gm',
+ '../include/private',
+ '../src/core',
+ '../src/effects',
+ '../src/gpu',
+ '../src/images',
+ '../src/image',
+ '../tools/timer',
+ ],
+ 'sources': [
+ '../gm/gm.cpp',
+ '<!@(python find.py ../tools/viewer "*.cpp")',
+ ],
+ 'dependencies': [
+ 'flags.gyp:flags',
+ 'gputest.gyp:skgputest',
+ 'jsoncpp.gyp:jsoncpp',
+ 'skia_lib.gyp:skia_lib',
+ 'tools.gyp:crash_handler',
+ 'tools.gyp:proc_stats',
+ 'tools.gyp:resources',
+ 'tools.gyp:sk_tool_utils',
+ '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)$'],
+ ],
+ }],
+ ],
+ },
+ ],
+}
+++ /dev/null
-# Copyright 2016 Google Inc.
-#
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# GYP file to build performance testbench.
-#
-{
- 'includes': [
- 'apptype_console.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'vulkanviewer',
- 'type': 'executable',
- 'includes' : [
- 'gmslides.gypi',
- ],
- 'include_dirs': [
- '../bench',
- '../gm',
- '../include/private',
- '../src/core',
- '../src/effects',
- '../src/gpu',
- '../src/images',
- '../src/image',
- '../tools/timer',
- ],
- 'sources': [
- '../gm/gm.cpp',
- '<!@(python find.py ../tools/vulkan "*.cpp")',
- ],
- 'dependencies': [
- 'flags.gyp:flags',
- 'gputest.gyp:skgputest',
- 'jsoncpp.gyp:jsoncpp',
- 'skia_lib.gyp:skia_lib',
- 'tools.gyp:crash_handler',
- 'tools.gyp:proc_stats',
- 'tools.gyp:resources',
- 'tools.gyp:sk_tool_utils',
- '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)$'],
- ],
- }],
- ],
- },
- ],
-}
include ':visualbench'
include ':visualbenchsdl'
include ':canvasproof'
-include ':vulkanviewer'
+include ':viewer'
--- /dev/null
+/*
+ * 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.viewer"
+ minSdkVersion 19
+ 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 {}; }
+
+ setupSkiaLibraryBuild(project, applicationVariants, "--vulkan CopyViewerDeps", true)
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- BEGIN_INCLUDE(manifest) -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.skia.viewer"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application
+ android:allowBackup="false"
+ android:label="Viewer">
+
+ <activity android:name=".ViewerActivity"
+ android:label="Viewer"
+ android:screenOrientation="portrait"
+ android:configChanges="orientation|keyboardHidden">
+ <meta-data android:name="android.app.lib_name"
+ android:value="viewer" />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
+<!-- END_INCLUDE(manifest) -->
--- /dev/null
+/*
+ * 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 org.skia.viewer;
+
+import android.app.ActionBar;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.view.WindowManager;
+
+public class ViewerActivity extends android.app.NativeActivity {
+ static {
+ System.loadLibrary("skia_android");
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ ActionBar ab = this.getActionBar();
+ ab.hide();
+ }
+}
+++ /dev/null
-/*
- * 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 19
- 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 {}; }
-
- setupSkiaLibraryBuild(project, applicationVariants, "--vulkan CopyVulkanViewerDeps", true)
-}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!-- BEGIN_INCLUDE(manifest) -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.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) -->
+++ /dev/null
-/*
- * 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 org.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();
- }
-}
},
'includes' : [
'canvasproof.gypi',
- 'vulkanviewer.gypi',
+ 'viewer.gypi',
],
'targets': [
{
--- /dev/null
+# 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': 'CopyViewerDeps',
+ 'type': 'none',
+ 'dependencies': [
+ 'skia_lib.gyp:skia_lib',
+ 'viewer.gyp:viewer',
+ ],
+ 'copies': [
+ {
+ 'destination': '<(android_base)/apps/viewer/src/main/libs/<(android_arch)',
+ 'conditions': [
+ [ 'skia_shared_lib', {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libskia_android.so',
+ '<(SHARED_LIB_DIR)/libviewer.so',
+ ]}, {
+ 'files': [
+ '<(SHARED_LIB_DIR)/libviewer.so',
+ ]}
+ ],
+ ],
+ },
+ ],
+ },
+ {
+ 'target_name': 'Viewer_APK',
+ 'type': 'none',
+ 'dependencies': [ 'CopyViewerDeps', ],
+ 'actions': [
+ {
+ 'action_name': 'SkiaViewer_apk',
+ 'inputs': [
+ '<(android_base)/apps/viewer/src/main/AndroidManifest.xml',
+ '<(android_base)/apps/viewer/src/main/java/org/skia/viewer/ViewerActivity.java',
+ '<(android_base)/apps/viewer/src/main/libs/<(android_arch)/libviewer.so',
+
+ ],
+ 'conditions': [
+ [ 'skia_shared_lib', {
+ 'inputs': [
+ '<(android_base)/apps/viewer/src/main/libs/<(android_arch)/libskia_android.so',
+ ],
+ }],
+ ],
+ 'outputs': [
+ '../apps/viewer/build/outputs/apk/',
+ ],
+ 'action': [
+ '<(android_base)/apps/gradlew',
+ ':viewer:assemble<(android_variant)<(android_buildtype)',
+ '-p<(android_base)/apps/viewer',
+ '-PsuppressNativeBuild',
+ '--daemon',
+ ],
+ },
+ ],
+ },
+ ],
+}
+++ /dev/null
-# 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)<(android_buildtype)',
- '-p<(android_base)/apps/vulkanviewer',
- '-PsuppressNativeBuild',
- '--daemon',
- ],
- },
- ],
- },
- ],
-}
--- /dev/null
+/*
+* 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 Application_DEFINED
+#define Application_DEFINED
+
+namespace sk_app {
+
+class Application {
+public:
+ static Application* Create(int argc, char** argv, void* platformData);
+
+ virtual ~Application() {}
+
+ virtual void onIdle(double ms) = 0;
+};
+
+} // namespace sk_app
+
+#endif
--- /dev/null
+
+/*
+ * 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 "GrContext.h"
+#include "SkSurface.h"
+#include "VulkanTestContext.h"
+
+#include "vk/GrVkInterface.h"
+#include "vk/GrVkUtil.h"
+#include "vk/GrVkTypes.h"
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
+#undef CreateSemaphore
+#endif
+
+#define GET_PROC(F) f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
+#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
+
+VulkanTestContext::VulkanTestContext(void* platformData, int msaaSampleCount)
+ : fSurface(VK_NULL_HANDLE)
+ , fSwapchain(VK_NULL_HANDLE)
+ , fCommandPool(VK_NULL_HANDLE)
+ , fBackbuffers(nullptr) {
+
+ // any config code here (particularly for msaa)?
+
+ this->initializeContext(platformData);
+}
+
+void VulkanTestContext::initializeContext(void* platformData) {
+
+ fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent));
+ if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
+ !(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) {
+ fBackendContext.reset(nullptr);
+ return;
+ }
+
+ VkInstance instance = fBackendContext->fInstance;
+ VkDevice device = fBackendContext->fDevice;
+ GET_PROC(DestroySurfaceKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
+ GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
+ GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
+ GET_DEV_PROC(CreateSwapchainKHR);
+ GET_DEV_PROC(DestroySwapchainKHR);
+ GET_DEV_PROC(GetSwapchainImagesKHR);
+ GET_DEV_PROC(AcquireNextImageKHR);
+ GET_DEV_PROC(QueuePresentKHR);
+
+ fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext)fBackendContext.get());
+
+ fSurface = createVkSurface(instance, platformData);
+ if (VK_NULL_HANDLE == fSurface) {
+ fBackendContext.reset(nullptr);
+ return;
+ }
+
+ VkBool32 supported;
+ VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fBackendContext->fPhysicalDevice,
+ fPresentQueueIndex, fSurface,
+ &supported);
+ if (VK_SUCCESS != res) {
+ this->destroyContext();
+ return;
+ }
+
+ if (!this->createSwapchain(-1, -1)) {
+ this->destroyContext();
+ return;
+ }
+
+ // create presentQueue
+ vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
+}
+
+bool VulkanTestContext::createSwapchain(uint32_t width, uint32_t height)
+{
+ // check for capabilities
+ VkSurfaceCapabilitiesKHR caps;
+ VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fBackendContext->fPhysicalDevice,
+ fSurface, &caps);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t surfaceFormatCount;
+ res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
+ &surfaceFormatCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
+ VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
+ res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
+ &surfaceFormatCount, surfaceFormats);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ uint32_t presentModeCount;
+ res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
+ &presentModeCount, nullptr);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
+ VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
+ res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
+ &presentModeCount, presentModes);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ VkExtent2D extent = caps.currentExtent;
+ // use the hints
+ if (extent.width == (uint32_t)-1) {
+ extent.width = width;
+ extent.height = height;
+ }
+
+ // clamp width; to protect us from broken hints
+ if (extent.width < caps.minImageExtent.width) {
+ extent.width = caps.minImageExtent.width;
+ } else if (extent.width > caps.maxImageExtent.width) {
+ extent.width = caps.maxImageExtent.width;
+ }
+ // clamp height
+ if (extent.height < caps.minImageExtent.height) {
+ extent.height = caps.minImageExtent.height;
+ } else if (extent.height > caps.maxImageExtent.height) {
+ extent.height = caps.maxImageExtent.height;
+ }
+ fWidth = (int)extent.width;
+ fHeight = (int)extent.height;
+
+ uint32_t imageCount = caps.minImageCount + 2;
+ if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
+ // Application must settle for fewer images than desired:
+ imageCount = caps.maxImageCount;
+ }
+
+ VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
+ SkASSERT(caps.supportedTransforms & caps.currentTransform);
+ SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
+ VkCompositeAlphaFlagBitsKHR composite_alpha =
+ (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
+ VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
+ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ // Pick our surface format -- for now, the first one
+ VkFormat surfaceFormat = surfaceFormats[0].format;
+ VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace;
+
+ // If mailbox mode is available, use it, as it is the lowest-latency non-
+ // tearing mode. If not, fall back to FIFO which is always available.
+ VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
+ for (uint32_t i = 0; i < presentModeCount; ++i) {
+ // use mailbox
+ if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
+ mode = presentModes[i];
+ break;
+ }
+ }
+
+ VkSwapchainCreateInfoKHR swapchainCreateInfo;
+ memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
+ swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapchainCreateInfo.surface = fSurface;
+ swapchainCreateInfo.minImageCount = imageCount;
+ swapchainCreateInfo.imageFormat = surfaceFormat;
+ swapchainCreateInfo.imageColorSpace = colorSpace;
+ swapchainCreateInfo.imageExtent = extent;
+ swapchainCreateInfo.imageArrayLayers = 1;
+ swapchainCreateInfo.imageUsage = usageFlags;
+
+ uint32_t queueFamilies[] = { fBackendContext->fGraphicsQueueIndex, fPresentQueueIndex };
+ if (fBackendContext->fGraphicsQueueIndex != fPresentQueueIndex) {
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
+ swapchainCreateInfo.queueFamilyIndexCount = 2;
+ swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
+ } else {
+ swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapchainCreateInfo.queueFamilyIndexCount = 0;
+ swapchainCreateInfo.pQueueFamilyIndices = nullptr;
+ }
+
+ swapchainCreateInfo.preTransform = caps.currentTransform;;
+ swapchainCreateInfo.compositeAlpha = composite_alpha;
+ swapchainCreateInfo.presentMode = mode;
+ swapchainCreateInfo.clipped = true;
+ swapchainCreateInfo.oldSwapchain = fSwapchain;
+
+ res = fCreateSwapchainKHR(fBackendContext->fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
+ if (VK_SUCCESS != res) {
+ return false;
+ }
+
+ // destroy the old swapchain
+ if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
+ GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
+
+ this->destroyBuffers();
+
+ fDestroySwapchainKHR(fBackendContext->fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
+ }
+
+ this->createBuffers(swapchainCreateInfo.imageFormat);
+
+ return true;
+}
+
+void VulkanTestContext::createBuffers(VkFormat format) {
+ GrVkFormatToPixelConfig(format, &fPixelConfig);
+
+ fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, nullptr);
+ SkASSERT(fImageCount);
+ fImages = new VkImage[fImageCount];
+ fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, fImages);
+
+ // set up initial image layouts and create surfaces
+ fImageLayouts = new VkImageLayout[fImageCount];
+ fSurfaces = new sk_sp<SkSurface>[fImageCount];
+ for (uint32_t i = 0; i < fImageCount; ++i) {
+ fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ GrBackendRenderTargetDesc desc;
+ GrVkTextureInfo info;
+ info.fImage = fImages[i];
+ info.fAlloc = VK_NULL_HANDLE;
+ info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
+ info.fFormat = format;
+ desc.fWidth = fWidth;
+ desc.fHeight = fHeight;
+ desc.fConfig = fPixelConfig;
+ desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+ desc.fSampleCnt = 0;
+ desc.fStencilBits = 0;
+ desc.fRenderTargetHandle = (GrBackendObject) &info;
+ SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
+ fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(fContext, desc, &props);
+ }
+
+ // create the command pool for the command buffers
+ if (VK_NULL_HANDLE == fCommandPool) {
+ VkCommandPoolCreateInfo commandPoolInfo;
+ memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo));
+ commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ // this needs to be on the render queue
+ commandPoolInfo.queueFamilyIndex = fBackendContext->fGraphicsQueueIndex;
+ commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ CreateCommandPool(fBackendContext->fDevice, &commandPoolInfo,
+ nullptr, &fCommandPool));
+ }
+
+ // set up the backbuffers
+ VkSemaphoreCreateInfo semaphoreInfo;
+ memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.pNext = nullptr;
+ semaphoreInfo.flags = 0;
+ VkCommandBufferAllocateInfo commandBuffersInfo;
+ memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
+ commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ commandBuffersInfo.pNext = nullptr;
+ commandBuffersInfo.commandPool = fCommandPool;
+ commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ commandBuffersInfo.commandBufferCount = 2;
+ VkFenceCreateInfo fenceInfo;
+ memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
+ fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceInfo.pNext = nullptr;
+ fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+
+ // we create one additional backbuffer structure here, because we want to
+ // give the command buffers they contain a chance to finish before we cycle back
+ fBackbuffers = new BackbufferInfo[fImageCount + 1];
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ fBackbuffers[i].fImageIndex = -1;
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
+ nullptr, &fBackbuffers[i].fAcquireSemaphore));
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
+ nullptr, &fBackbuffers[i].fRenderSemaphore));
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ AllocateCommandBuffers(fBackendContext->fDevice, &commandBuffersInfo,
+ fBackbuffers[i].fTransitionCmdBuffers));
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
+ &fBackbuffers[i].fUsageFences[0]));
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
+ &fBackbuffers[i].fUsageFences[1]));
+ }
+ fCurrentBackbufferIndex = fImageCount;
+}
+
+void VulkanTestContext::destroyBuffers() {
+
+ if (fBackbuffers) {
+ for (uint32_t i = 0; i < fImageCount + 1; ++i) {
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ WaitForFences(fBackendContext->fDevice, 2,
+ fBackbuffers[i].fUsageFences,
+ true, UINT64_MAX));
+ fBackbuffers[i].fImageIndex = -1;
+ GR_VK_CALL(fBackendContext->fInterface,
+ DestroySemaphore(fBackendContext->fDevice,
+ fBackbuffers[i].fAcquireSemaphore,
+ nullptr));
+ GR_VK_CALL(fBackendContext->fInterface,
+ DestroySemaphore(fBackendContext->fDevice,
+ fBackbuffers[i].fRenderSemaphore,
+ nullptr));
+ GR_VK_CALL(fBackendContext->fInterface,
+ FreeCommandBuffers(fBackendContext->fDevice, fCommandPool, 2,
+ fBackbuffers[i].fTransitionCmdBuffers));
+ GR_VK_CALL(fBackendContext->fInterface,
+ DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[0], 0));
+ GR_VK_CALL(fBackendContext->fInterface,
+ DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[1], 0));
+ }
+ }
+
+ delete[] fBackbuffers;
+ fBackbuffers = nullptr;
+
+ delete[] fSurfaces;
+ fSurfaces = nullptr;
+ delete[] fImageLayouts;
+ fImageLayouts = nullptr;
+ delete[] fImages;
+ fImages = nullptr;
+}
+
+VulkanTestContext::~VulkanTestContext() {
+ this->destroyContext();
+}
+
+void VulkanTestContext::destroyContext() {
+ if (!fBackendContext.get()) {
+ return;
+ }
+
+ GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
+
+ this->destroyBuffers();
+
+ if (VK_NULL_HANDLE != fCommandPool) {
+ GR_VK_CALL(fBackendContext->fInterface, DestroyCommandPool(fBackendContext->fDevice,
+ fCommandPool, nullptr));
+ fCommandPool = VK_NULL_HANDLE;
+ }
+
+ if (VK_NULL_HANDLE != fSwapchain) {
+ fDestroySwapchainKHR(fBackendContext->fDevice, fSwapchain, nullptr);
+ fSwapchain = VK_NULL_HANDLE;
+ }
+
+ if (VK_NULL_HANDLE != fSurface) {
+ fDestroySurfaceKHR(fBackendContext->fInstance, fSurface, nullptr);
+ fSurface = VK_NULL_HANDLE;
+ }
+
+ delete fContext;
+
+ fBackendContext.reset(nullptr);
+}
+
+VulkanTestContext::BackbufferInfo* VulkanTestContext::getAvailableBackbuffer() {
+ SkASSERT(fBackbuffers);
+
+ ++fCurrentBackbufferIndex;
+ if (fCurrentBackbufferIndex > fImageCount) {
+ fCurrentBackbufferIndex = 0;
+ }
+
+ BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
+
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ WaitForFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences,
+ true, UINT64_MAX));
+ return backbuffer;
+}
+
+SkSurface* VulkanTestContext::getBackbufferSurface() {
+ BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
+ SkASSERT(backbuffer);
+
+ // reset the fence
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ ResetFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences));
+ // semaphores should be in unsignaled state
+
+ // acquire the image
+ VkResult res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
+ backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+ if (VK_ERROR_SURFACE_LOST_KHR == res) {
+ // need to figure out how to create a new vkSurface without the platformData*
+ // maybe use attach somehow? but need a Window
+ return nullptr;
+ }
+ if (VK_ERROR_OUT_OF_DATE_KHR == res) {
+ // tear swapchain down and try again
+ if (!this->createSwapchain(0, 0)) {
+ return nullptr;
+ }
+
+ // acquire the image
+ res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
+ backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
+ &backbuffer->fImageIndex);
+
+ if (VK_SUCCESS != res) {
+ return nullptr;
+ }
+ }
+
+ // set up layout transfer from initial to color attachment
+ VkImageLayout layout = fImageLayouts[backbuffer->fImageIndex];
+ VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
+ 0 : VK_ACCESS_MEMORY_READ_BIT;
+ VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+
+ VkImageMemoryBarrier imageMemoryBarrier = {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
+ fPresentQueueIndex, // srcQueueFamilyIndex
+ fBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
+ fImages[backbuffer->fImageIndex], // image
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ };
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[0], 0));
+ VkCommandBufferBeginInfo info;
+ memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ info.flags = 0;
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[0], &info));
+
+ GR_VK_CALL(fBackendContext->fInterface,
+ CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[0],
+ srcStageMask, dstStageMask, 0,
+ 0, nullptr,
+ 0, nullptr,
+ 1, &imageMemoryBarrier));
+
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ EndCommandBuffer(backbuffer->fTransitionCmdBuffers[0]));
+
+ VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ // insert the layout transfer into the queue and wait on the acquire
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = &backbuffer->fAcquireSemaphore;
+ submitInfo.pWaitDstStageMask = &waitDstStageFlags;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[0];
+ submitInfo.signalSemaphoreCount = 0;
+
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
+ backbuffer->fUsageFences[0]));
+
+ return fSurfaces[backbuffer->fImageIndex].get();
+}
+
+
+void VulkanTestContext::swapBuffers() {
+
+ BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
+
+ VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+ VkAccessFlags srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+
+ VkImageMemoryBarrier imageMemoryBarrier = {
+ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
+ NULL, // pNext
+ srcAccessMask, // outputMask
+ dstAccessMask, // inputMask
+ layout, // oldLayout
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
+ fBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
+ fPresentQueueIndex, // dstQueueFamilyIndex
+ fImages[backbuffer->fImageIndex], // image
+ { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
+ };
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[1], 0));
+ VkCommandBufferBeginInfo info;
+ memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
+ info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ info.flags = 0;
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[1], &info));
+ GR_VK_CALL(fBackendContext->fInterface,
+ CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[1],
+ srcStageMask, dstStageMask, 0,
+ 0, nullptr,
+ 0, nullptr,
+ 1, &imageMemoryBarrier));
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ EndCommandBuffer(backbuffer->fTransitionCmdBuffers[1]));
+
+ fImageLayouts[backbuffer->fImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ // insert the layout transfer into the queue and wait on the acquire
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitDstStageMask = 0;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[1];
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &backbuffer->fRenderSemaphore;
+
+ GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
+ QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
+ backbuffer->fUsageFences[1]));
+
+ // Submit present operation to present queue
+ const VkPresentInfoKHR presentInfo =
+ {
+ VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
+ NULL, // pNext
+ 1, // waitSemaphoreCount
+ &backbuffer->fRenderSemaphore, // pWaitSemaphores
+ 1, // swapchainCount
+ &fSwapchain, // pSwapchains
+ &backbuffer->fImageIndex, // pImageIndices
+ NULL // pResults
+ };
+
+ fQueuePresentKHR(fPresentQueue, &presentInfo);
+
+}
--- /dev/null
+
+/*
+ * 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_DEFINED
+#define VulkanTestContext_DEFINED
+
+#ifdef SK_VULKAN
+
+#include "GrTypes.h"
+#include "vk/GrVkBackendContext.h"
+
+class SkSurface;
+class GrContext;
+
+class VulkanTestContext {
+public:
+ ~VulkanTestContext();
+
+ // each platform will have to implement these in its CPP file
+ static VkSurfaceKHR createVkSurface(VkInstance, void* platformData);
+ static bool canPresent(VkInstance, VkPhysicalDevice, uint32_t queueFamilyIndex);
+
+ static VulkanTestContext* Create(void* platformData, int msaaSampleCount) {
+ VulkanTestContext* ctx = new VulkanTestContext(platformData, msaaSampleCount);
+ if (!ctx->isValid()) {
+ delete ctx;
+ return nullptr;
+ }
+ return ctx;
+ }
+
+ SkSurface* getBackbufferSurface();
+ void swapBuffers();
+
+ bool makeCurrent() { return true; }
+
+ bool isValid() { return SkToBool(fBackendContext.get()); }
+
+ void resize(uint32_t w, uint32_t h) {
+ this->createSwapchain(w, h);
+ }
+
+ GrBackendContext getBackendContext() { return (GrBackendContext)fBackendContext.get(); }
+
+private:
+ VulkanTestContext();
+ VulkanTestContext(void*, int msaaSampleCount);
+ void initializeContext(void*);
+ void destroyContext();
+
+ struct BackbufferInfo {
+ uint32_t fImageIndex; // image this is associated with
+ VkSemaphore fAcquireSemaphore; // we signal on this for acquisition of image
+ VkSemaphore fRenderSemaphore; // we wait on this for rendering to be done
+ VkCommandBuffer fTransitionCmdBuffers[2]; // to transition layout between present and render
+ VkFence fUsageFences[2]; // used to ensure this data is no longer used on GPU
+ };
+
+ BackbufferInfo* getAvailableBackbuffer();
+ bool createSwapchain(uint32_t width, uint32_t height);
+ void createBuffers(VkFormat format);
+ void destroyBuffers();
+
+ SkAutoTUnref<const GrVkBackendContext> fBackendContext;
+
+ // simple wrapper class that exists only to initialize a pointer to NULL
+ template <typename FNPTR_TYPE> class VkPtr {
+ public:
+ VkPtr() : fPtr(NULL) {}
+ VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
+ operator FNPTR_TYPE() const { return fPtr; }
+ private:
+ FNPTR_TYPE fPtr;
+ };
+
+ // WSI interface functions
+ VkPtr<PFN_vkDestroySurfaceKHR> fDestroySurfaceKHR;
+ VkPtr<PFN_vkGetPhysicalDeviceSurfaceSupportKHR> fGetPhysicalDeviceSurfaceSupportKHR;
+ VkPtr<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR> fGetPhysicalDeviceSurfaceCapabilitiesKHR;
+ VkPtr<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR> fGetPhysicalDeviceSurfaceFormatsKHR;
+ VkPtr<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR> fGetPhysicalDeviceSurfacePresentModesKHR;
+
+ VkPtr<PFN_vkCreateSwapchainKHR> fCreateSwapchainKHR;
+ VkPtr<PFN_vkDestroySwapchainKHR> fDestroySwapchainKHR;
+ VkPtr<PFN_vkGetSwapchainImagesKHR> fGetSwapchainImagesKHR;
+ VkPtr<PFN_vkAcquireNextImageKHR> fAcquireNextImageKHR;
+ VkPtr<PFN_vkQueuePresentKHR> fQueuePresentKHR;
+ VkPtr<PFN_vkCreateSharedSwapchainsKHR> fCreateSharedSwapchainsKHR;
+
+ GrContext* fContext;
+ VkSurfaceKHR fSurface;
+ VkSwapchainKHR fSwapchain;
+ uint32_t fPresentQueueIndex;
+ VkQueue fPresentQueue;
+ int fWidth;
+ int fHeight;
+ GrPixelConfig fPixelConfig;
+
+ uint32_t fImageCount;
+ VkImage* fImages; // images in the swapchain
+ VkImageLayout* fImageLayouts; // layouts of these images when not color attachment
+ sk_sp<SkSurface>* fSurfaces; // wrapped surface for those images
+ VkCommandPool fCommandPool;
+ BackbufferInfo* fBackbuffers;
+ uint32_t fCurrentBackbufferIndex;
+};
+
+#endif // SK_VULKAN
+
+#endif
--- /dev/null
+/*
+* 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.h"
+
+#include "SkSurface.h"
+#include "SkCanvas.h"
+#include "VulkanTestContext.h"
+
+namespace sk_app {
+
+static bool default_char_func(SkUnichar c, uint32_t modifiers, void* userData) {
+ return false;
+}
+
+static bool default_key_func(Window::Key key, Window::InputState state, uint32_t modifiers,
+ void* userData) {
+ return false;
+}
+
+static bool default_mouse_func(int x, int y, Window::InputState state, uint32_t modifiers,
+ void* userData) {
+ return false;
+}
+
+static void default_paint_func(SkCanvas*, void* userData) {}
+
+Window::Window() : fCharFunc(default_char_func)
+ , fKeyFunc(default_key_func)
+ , fMouseFunc(default_mouse_func)
+ , fPaintFunc(default_paint_func) {
+}
+
+void Window::detach() {
+ delete fTestContext;
+ fTestContext = nullptr;
+}
+
+bool Window::onChar(SkUnichar c, uint32_t modifiers) {
+ return fCharFunc(c, modifiers, fCharUserData);
+}
+
+bool Window::onKey(Key key, InputState state, uint32_t modifiers) {
+ return fKeyFunc(key, state, modifiers, fKeyUserData);
+}
+
+bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
+ return fMouseFunc(x, y, state, modifiers, fMouseUserData);
+}
+
+void Window::onPaint() {
+ SkSurface* backbuffer = fTestContext->getBackbufferSurface();
+ if (backbuffer) {
+ // draw into the canvas of this surface
+ SkCanvas* canvas = backbuffer->getCanvas();
+
+ fPaintFunc(canvas, fPaintUserData);
+
+ canvas->flush();
+
+ fTestContext->swapBuffers();
+ } else {
+ // try recreating testcontext
+ }
+
+}
+
+void Window::onResize(uint32_t w, uint32_t h) {
+ fWidth = w;
+ fHeight = h;
+ fTestContext->resize(w, h);
+}
+
+} // namespace sk_app
--- /dev/null
+/*
+* 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_DEFINED
+#define Window_DEFINED
+
+#include "SkTypes.h"
+#include "SkRect.h"
+
+class SkCanvas;
+class VulkanTestContext;
+
+namespace sk_app {
+
+class Window {
+public:
+ static Window* CreateNativeWindow(void* platformData);
+
+ virtual ~Window() {};
+
+ virtual void setTitle(const char*) = 0;
+ 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(); }
+
+ enum BackEndType {
+ kNativeGL_BackendType,
+ kVulkan_BackendType
+ };
+
+ virtual bool attach(BackEndType attachType, int msaaSampleCount) = 0;
+ void detach();
+
+ // input handling
+ enum Key {
+ kNONE_Key, //corresponds to android's UNKNOWN
+
+ kLeftSoftKey_Key,
+ kRightSoftKey_Key,
+
+ kHome_Key, //!< the home key - added to match android
+ kBack_Key, //!< (CLR)
+ kSend_Key, //!< the green (talk) key
+ kEnd_Key, //!< the red key
+
+ k0_Key,
+ k1_Key,
+ k2_Key,
+ k3_Key,
+ k4_Key,
+ k5_Key,
+ k6_Key,
+ k7_Key,
+ k8_Key,
+ k9_Key,
+ kStar_Key, //!< the * key
+ kHash_Key, //!< the # key
+
+ kUp_Key,
+ kDown_Key,
+ kLeft_Key,
+ kRight_Key,
+
+ kOK_Key, //!< the center key
+
+ kVolUp_Key, //!< volume up - match android
+ kVolDown_Key, //!< volume down - same
+ kPower_Key, //!< power button - same
+ kCamera_Key, //!< camera - same
+
+ kLast_Key = kCamera_Key
+ };
+ static const int kKeyCount = kLast_Key + 1;
+
+ enum ModifierKeys {
+ kShift_ModifierKey = 1 << 0,
+ kControl_ModifierKey = 1 << 1,
+ kOption_ModifierKey = 1 << 2, // same as ALT
+ kCommand_ModifierKey = 1 << 3,
+ kFirstPress_ModifierKey = 1 << 4,
+ };
+
+ enum InputState {
+ kDown_InputState,
+ kUp_InputState,
+ kMove_InputState // only valid for mouse
+ };
+
+ // return value of 'true' means 'I have handled this event'
+ typedef bool(*OnCharFunc)(SkUnichar c, uint32_t modifiers, void* userData);
+ typedef bool(*OnKeyFunc)(Key key, InputState state, uint32_t modifiers, void* userData);
+ typedef bool(*OnMouseFunc)(int x, int y, InputState state, uint32_t modifiers, void* userData);
+ typedef void(*OnPaintFunc)(SkCanvas*, void* userData);
+
+ void registerCharFunc(OnCharFunc func, void* userData) {
+ fCharFunc = func;
+ fCharUserData = userData;
+ }
+
+ void registerKeyFunc(OnKeyFunc func, void* userData) {
+ fKeyFunc = func;
+ fKeyUserData = userData;
+ }
+
+ void registerMouseFunc(OnMouseFunc func, void* userData) {
+ fMouseFunc = func;
+ fMouseUserData = userData;
+ }
+
+ void registerPaintFunc(OnPaintFunc func, void* userData) {
+ fPaintFunc = func;
+ fPaintUserData = userData;
+ }
+
+ bool onChar(SkUnichar c, uint32_t modifiers);
+ bool onKey(Key key, InputState state, uint32_t modifiers);
+ bool onMouse(int x, int y, InputState state, uint32_t modifiers);
+ void onPaint();
+ void onResize(uint32_t width, uint32_t height);
+
+ uint32_t width() { return fWidth; }
+ uint32_t height() { return fHeight; }
+
+protected:
+ Window();
+
+ uint32_t fWidth;
+ uint32_t fHeight;
+
+ OnCharFunc fCharFunc;
+ void* fCharUserData;
+ OnKeyFunc fKeyFunc;
+ void* fKeyUserData;
+ OnMouseFunc fMouseFunc;
+ void* fMouseUserData;
+ OnPaintFunc fPaintFunc;
+ void* fPaintUserData;
+
+ VulkanTestContext* fTestContext;
+};
+
+} // namespace sk_app
+#endif
--- /dev/null
+
+/*
+ * 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 "VulkanTestContext_android.h"
+
+#include "vk/GrVkInterface.h"
+#include "vk/GrVkUtil.h"
+
+VkSurfaceKHR VulkanTestContext::createVkSurface(VkInstance instance, void* platformData) {
+ static PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR = nullptr;
+ if (!createAndroidSurfaceKHR) {
+ createAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance,
+ "vkCreateAndroidSurfaceKHR");
+ }
+
+ if (!platformData) {
+ return VK_NULL_HANDLE;
+ }
+ 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 = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
+ nullptr, &surface);
+ return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
+}
+
+bool VulkanTestContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
+ uint32_t queueFamilyIndex) {
+ return true;
+}
--- /dev/null
+
+/*
+ * 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
--- /dev/null
+/*
+* 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"
+
+namespace sk_app {
+
+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) {
+ 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;
+}
+
+} // namespace sk_app
--- /dev/null
+/*
+* 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>
+
+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);
+ void initDisplay(ANativeWindow* window);
+
+ void setTitle(const char*) override;
+ void show() override {}
+
+ bool attach(BackEndType attachType, int msaaSampleCount) 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;
+};
+
+} // namespace sk_app
+
+#endif
--- /dev/null
+/*
+* 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; }
+
+using sk_app::Application;
+
+/**
+ * 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[] = {
+ "viewer",
+ "--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)
--- /dev/null
+/*
+* Copyright 2016 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+/*
+* Copyright 2014 Google Inc.
+*
+* Use of this source code is governed by a BSD-style license that can be
+* found in the LICENSE file.
+*/
+
+#include "GMSlide.h"
+#include "SkCanvas.h"
+
+GMSlide::GMSlide(skiagm::GM* gm) : fGM(gm) {
+ fName.printf("GM_%s", gm->getName());
+}
+
+GMSlide::~GMSlide() { delete fGM; }
+
+void GMSlide::draw(SkCanvas* canvas) {
+ // Do we care about timing the draw of the background (once)?
+ // Does the GM ever rely on drawBackground to lazily compute something?
+ fGM->drawBackground(canvas);
+ fGM->drawContent(canvas);
+}
+
+bool GMSlide::animate(const SkAnimTimer& timer) {
+ return fGM->animate(timer);
+}
--- /dev/null
+/*
+* 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 GMSlide_DEFINED
+#define GMSlide_DEFINED
+
+#include "Slide.h"
+#include "gm.h"
+
+class GMSlide : public Slide {
+public:
+ GMSlide(skiagm::GM* gm);
+ ~GMSlide() override;
+
+ SkISize getDimensions() const override { return fGM->getISize(); }
+
+ void draw(SkCanvas* canvas) override;
+ bool animate(const SkAnimTimer&) override;
+
+private:
+ skiagm::GM* fGM;
+};
+
+
+#endif
--- /dev/null
+/*
+* 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 "SKPSlide.h"
+
+#include "SkCanvas.h"
+#include "SkCommonFlags.h"
+#include "SkOSFile.h"
+#include "SkStream.h"
+
+SKPSlide::SKPSlide(const SkString& name, const SkString& path) : fPath(path) {
+ fName = name;
+}
+
+SKPSlide::~SKPSlide() {}
+
+void SKPSlide::draw(SkCanvas* canvas) {
+ if (fPic.get()) {
+ bool isOffset = SkToBool(fCullRect.left() | fCullRect.top());
+ if (isOffset) {
+ canvas->save();
+ canvas->translate(SkIntToScalar(-fCullRect.left()), SkIntToScalar(-fCullRect.top()));
+ }
+
+ canvas->drawPicture(fPic.get());
+
+ if (isOffset) {
+ canvas->restore();
+ }
+ }
+}
+
+static sk_sp<SkPicture> read_picture(const char path[]) {
+ SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
+ if (stream.get() == nullptr) {
+ SkDebugf("Could not read %s.\n", path);
+ return nullptr;
+ }
+
+ auto pic = SkPicture::MakeFromStream(stream.get());
+ if (!pic) {
+ SkDebugf("Could not read %s as an SkPicture.\n", path);
+ }
+ return pic;
+}
+
+void SKPSlide::load() {
+ fPic = read_picture(fPath.c_str());
+ fCullRect = fPic->cullRect().roundOut();
+}
+
+void SKPSlide::unload() {
+ fPic.reset(nullptr);
+}
--- /dev/null
+/*
+* 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 SKPSlide_DEFINED
+#define SKPSlide_DEFINED
+
+#include "Slide.h"
+#include "SkPicture.h"
+
+class SKPSlide : public Slide {
+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;
+
+private:
+ SkString fPath;
+ sk_sp<const SkPicture> fPic;
+ SkIRect fCullRect;
+};
+
+#endif
--- /dev/null
+/*
+* 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 Slide_DEFINED
+#define Slide_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkSize.h"
+#include "SkString.h"
+
+class SkCanvas;
+class SkAnimTimer;
+
+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() {}
+ virtual void unload() {}
+
+ SkString getName() { return fName; }
+
+protected:
+ SkString fName;
+};
+
+
+#endif
--- /dev/null
+/*
+* 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 "Viewer.h"
+
+#include "GMSlide.h"
+#include "SKPSlide.h"
+
+#include "SkCanvas.h"
+#include "SkCommonFlags.h"
+#include "SkOSFile.h"
+#include "SkRandom.h"
+#include "SkStream.h"
+
+using namespace sk_app;
+
+Application* Application::Create(int argc, char** argv, void* platformData) {
+ return new Viewer(argc, argv, platformData);
+}
+
+static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
+ void* userData) {
+ Viewer* vv = reinterpret_cast<Viewer*>(userData);
+
+ return vv->onKey(key, state, modifiers);
+}
+
+static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
+ Viewer* vv = reinterpret_cast<Viewer*>(userData);
+
+ return vv->onChar(c, modifiers);
+}
+
+static void on_paint_handler(SkCanvas* canvas, void* userData) {
+ Viewer* vv = reinterpret_cast<Viewer*>(userData);
+
+ return vv->onPaint(canvas);
+}
+
+DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
+DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON identifying this builder.");
+DEFINE_string2(match, m, nullptr,
+ "[~][^]substring[$] [...] of bench name to run.\n"
+ "Multiple matches may be separated by spaces.\n"
+ "~ causes a matching bench to always be skipped\n"
+ "^ requires the start of the bench to match\n"
+ "$ requires the end of the bench to match\n"
+ "^ and $ requires an exact match\n"
+ "If a bench does not match any list entry,\n"
+ "it is skipped unless some list entry starts with ~");
+DEFINE_string(skps, "skps", "Directory to read skps from.");
+
+Viewer::Viewer(int argc, char** argv, void* platformData)
+ : fCurrentMeasurement(0)
+ , fDisplayStats(false)
+ , fZoomCenterX(0.0f)
+ , fZoomCenterY(0.0f)
+ , fZoomLevel(0.0f)
+ , fZoomScale(SK_Scalar1)
+{
+ memset(fMeasurements, 0, sizeof(fMeasurements));
+
+ SkDebugf("Command line arguments: ");
+ for (int i = 1; i < argc; ++i) {
+ SkDebugf("%s ", argv[i]);
+ }
+ SkDebugf("\n");
+
+ SkCommandLineFlags::Parse(argc, argv);
+
+ fWindow = Window::CreateNativeWindow(platformData);
+ fWindow->attach(Window::kVulkan_BackendType, 0);
+
+ // register callbacks
+ fWindow->registerKeyFunc(on_key_handler, this);
+ fWindow->registerCharFunc(on_char_handler, this);
+ fWindow->registerPaintFunc(on_paint_handler, this);
+
+ // set up slides
+ this->initSlides();
+
+ fAnimTimer.run();
+
+ // set up first frame
+ fCurrentSlide = 0;
+ setupCurrentSlide(-1);
+ updateMatrix();
+
+ fWindow->show();
+}
+
+void Viewer::initSlides() {
+ const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
+ while (gms) {
+ SkAutoTDelete<skiagm::GM> gm(gms->factory()(nullptr));
+
+ if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
+ sk_sp<Slide> slide(new GMSlide(gm.release()));
+ fSlides.push_back(slide);
+ }
+
+ gms = gms->next();
+ }
+
+ // reverse array
+ for (int i = 0; i < fSlides.count()/2; ++i) {
+ sk_sp<Slide> temp = fSlides[i];
+ fSlides[i] = fSlides[fSlides.count() - i - 1];
+ fSlides[fSlides.count() - i - 1] = temp;
+ }
+
+ // SKPs
+ for (int i = 0; i < FLAGS_skps.count(); i++) {
+ if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
+ continue;
+ }
+
+ SkString path(FLAGS_skps[i]);
+ sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
+ if (slide) {
+ fSlides.push_back(slide);
+ }
+ } else {
+ SkOSFile::Iter it(FLAGS_skps[i], ".skp");
+ SkString skpName;
+ while (it.next(&skpName)) {
+ if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
+ continue;
+ }
+
+ SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
+ sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
+ if (slide) {
+ fSlides.push_back(slide);
+ }
+ }
+ }
+ }
+}
+
+
+Viewer::~Viewer() {
+ fWindow->detach();
+ delete fWindow;
+}
+
+void Viewer::setupCurrentSlide(int previousSlide) {
+ SkString title("Viewer: ");
+ title.append(fSlides[fCurrentSlide]->getName());
+ fSlides[fCurrentSlide]->load();
+ if (previousSlide >= 0) {
+ fSlides[previousSlide]->unload();
+ }
+ fWindow->setTitle(title.c_str());
+ fWindow->inval();
+}
+
+#define MAX_ZOOM_LEVEL 8
+#define MIN_ZOOM_LEVEL -8
+
+void Viewer::changeZoomLevel(float delta) {
+ fZoomLevel += delta;
+ if (fZoomLevel > 0) {
+ fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
+ fZoomScale = fZoomLevel + SK_Scalar1;
+ } else if (fZoomLevel < 0) {
+ fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
+ fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
+ } else {
+ fZoomScale = SK_Scalar1;
+ }
+ this->updateMatrix();
+}
+
+void Viewer::updateMatrix(){
+ SkMatrix m;
+ m.reset();
+
+ if (fZoomLevel) {
+ SkPoint center;
+ //m = this->getLocalMatrix();//.invert(&m);
+ m.mapXY(fZoomCenterX, fZoomCenterY, ¢er);
+ SkScalar cx = center.fX;
+ SkScalar cy = center.fY;
+
+ m.setTranslate(-cx, -cy);
+ m.postScale(fZoomScale, fZoomScale);
+ m.postTranslate(cx, cy);
+ }
+
+ // TODO: add gesture support
+ // Apply any gesture matrix
+ //m.preConcat(fGesture.localM());
+ //m.preConcat(fGesture.globalM());
+
+ fLocalMatrix = m;
+}
+
+bool Viewer::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) {
+ if (Window::kDown_InputState == state) {
+ switch (key) {
+ case Window::kRight_Key: {
+ int previousSlide = fCurrentSlide;
+ fCurrentSlide++;
+ if (fCurrentSlide >= fSlides.count()) {
+ fCurrentSlide = 0;
+ }
+ setupCurrentSlide(previousSlide);
+ return true;
+ }
+
+ case Window::kLeft_Key: {
+ int previousSlide = fCurrentSlide;
+ fCurrentSlide--;
+ if (fCurrentSlide < 0) {
+ fCurrentSlide = fSlides.count() - 1;
+ }
+ SkString title("Viewer: ");
+ title.append(fSlides[fCurrentSlide]->getName());
+ fWindow->setTitle(title.c_str());
+ setupCurrentSlide(previousSlide);
+ return true;
+ }
+
+ case Window::kUp_Key: {
+ this->changeZoomLevel(1.f / 32.f);
+ fWindow->inval();
+ return true;
+ }
+
+ case Window::kDown_Key: {
+ this->changeZoomLevel(-1.f / 32.f);
+ fWindow->inval();
+ return true;
+ }
+
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
+ if ('s' == c) {
+ fDisplayStats = !fDisplayStats;
+ return true;
+ }
+
+ return false;
+}
+
+void Viewer::onPaint(SkCanvas* canvas) {
+
+ int count = canvas->save();
+
+ 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);
+
+ if (fDisplayStats) {
+ drawStats(canvas);
+ }
+}
+
+void Viewer::drawStats(SkCanvas* canvas) {
+ static const float kPixelPerMS = 2.0f;
+ static const int kDisplayWidth = 130;
+ static const int kDisplayHeight = 100;
+ static const int kDisplayPadding = 10;
+ static const int kGraphPadding = 3;
+ static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
+
+ SkISize canvasSize = canvas->getDeviceSize();
+ SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
+ SkIntToScalar(kDisplayPadding),
+ SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
+ 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);
+ // draw the 16ms line
+ paint.setColor(SK_ColorLTGRAY);
+ canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
+ rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
+ paint.setColor(SK_ColorRED);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(rect, paint);
+
+ int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
+ const int xStep = 2;
+ const int startY = SkScalarTruncToInt(rect.fBottom);
+ int i = fCurrentMeasurement;
+ do {
+ int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5); // round to nearest value
+ canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
+ SkIntToScalar(x), SkIntToScalar(endY), paint);
+ i++;
+ i &= (kMeasurementCount - 1); // fast mod
+ x += xStep;
+ } while (i != fCurrentMeasurement);
+
+ canvas->restore();
+}
+
+void Viewer::onIdle(double ms) {
+ // Record measurements
+ fMeasurements[fCurrentMeasurement++] = ms;
+ fCurrentMeasurement &= (kMeasurementCount - 1); // fast mod
+ SkASSERT(fCurrentMeasurement < kMeasurementCount);
+
+ fAnimTimer.updateTime();
+ if (fSlides[fCurrentSlide]->animate(fAnimTimer) || fDisplayStats) {
+ fWindow->inval();
+ }
+}
--- /dev/null
+/*
+* 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 Viewer_DEFINED
+#define Viewer_DEFINED
+
+#include "../Application.h"
+#include "../Window.h"
+#include "gm.h"
+#include "SkAnimTimer.h"
+#include "Slide.h"
+
+class SkCanvas;
+
+class Viewer : public sk_app::Application {
+public:
+ Viewer(int argc, char** argv, void* platformData);
+ ~Viewer() override;
+
+ bool onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers);
+ bool onChar(SkUnichar, uint32_t modifiers);
+ void onPaint(SkCanvas* canvas);
+ void onIdle(double ms) override;
+
+private:
+ void initSlides();
+ void setupCurrentSlide(int previousSlide);
+
+ void drawStats(SkCanvas* canvas);
+
+ void changeZoomLevel(float delta);
+ void updateMatrix();
+
+ sk_app::Window* fWindow;
+
+ static const int kMeasurementCount = 64; // should be power of 2 for fast mod
+ double fMeasurements[kMeasurementCount];
+ int fCurrentMeasurement;
+
+ SkAnimTimer fAnimTimer;
+ SkTArray<sk_sp<Slide>> fSlides;
+ int fCurrentSlide;
+
+ bool fDisplayStats;
+
+ // transform data
+ SkMatrix fLocalMatrix;
+ SkScalar fZoomCenterX;
+ SkScalar fZoomCenterY;
+ SkScalar fZoomLevel;
+ SkScalar fZoomScale;
+
+};
+
+
+#endif
--- /dev/null
+
+/*
+ * 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 "VulkanTestContext_win.h"
+
+#include "vk/GrVkInterface.h"
+#include "vk/GrVkUtil.h"
+
+// Platform dependant call
+VkSurfaceKHR VulkanTestContext::createVkSurface(VkInstance instance, void* platformData) {
+ static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
+ if (!createWin32SurfaceKHR) {
+ createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(instance,
+ "vkCreateWin32SurfaceKHR");
+ }
+
+ if (!platformData) {
+ return VK_NULL_HANDLE;
+ }
+ ContextPlatformData_win* winPlatformData =
+ reinterpret_cast<ContextPlatformData_win*>(platformData);
+ VkSurfaceKHR surface;
+
+ VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
+ memset(&surfaceCreateInfo, 0, sizeof(VkWin32SurfaceCreateInfoKHR));
+ surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surfaceCreateInfo.pNext = nullptr;
+ surfaceCreateInfo.flags = 0;
+ surfaceCreateInfo.hinstance = winPlatformData->fHInstance;
+ surfaceCreateInfo.hwnd = winPlatformData->fHWnd;
+
+ VkResult res = createWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
+ if (VK_SUCCESS != res) {
+ return VK_NULL_HANDLE;
+ }
+
+ return surface;
+}
+
+// Platform dependant call
+bool VulkanTestContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
+ uint32_t queueFamilyIndex) {
+ static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
+ getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
+ if (!getPhysicalDeviceWin32PresentationSupportKHR) {
+ getPhysicalDeviceWin32PresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) vkGetInstanceProcAddr(instance,
+ "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+ }
+
+ VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
+ return (VK_FALSE != check);
+}
--- /dev/null
+
+/*
+ * 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_WIN_DEFINED
+#define VULKANTESTCONTEXT_WIN_DEFINED
+
+#ifdef SK_VULKAN
+
+#include <windows.h>
+#include "../VulkanTestContext.h"
+
+// for Windows
+struct ContextPlatformData_win {
+ HINSTANCE fHInstance;
+ HWND fHWnd;
+};
+
+#endif // SK_VULKAN
+
+#endif
--- /dev/null
+/*
+* 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_win.h"
+
+#include <tchar.h>
+#include <windows.h>
+#include <windowsx.h>
+
+#include "SkUtils.h"
+#include "VulkanTestContext_win.h"
+
+namespace sk_app {
+
+Window* Window::CreateNativeWindow(void* platformData) {
+ HINSTANCE hInstance = (HINSTANCE)platformData;
+
+ Window_win* window = new Window_win();
+ if (!window->init(hInstance)) {
+ delete window;
+ return nullptr;
+ }
+
+ return window;
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+bool Window_win::init(HINSTANCE hInstance) {
+ fHInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
+
+ WNDCLASSEX wcex;
+ // The main window class name
+ static const TCHAR gSZWindowClass[] = _T("SkiaApp");
+
+ wcex.cbSize = sizeof(WNDCLASSEX);
+
+ wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wcex.lpfnWndProc = WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = fHInstance;
+ wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
+ wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);;
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wcex.lpszMenuName = nullptr;
+ wcex.lpszClassName = gSZWindowClass;
+ wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);;
+
+ if (!RegisterClassEx(&wcex)) {
+ return false;
+ }
+
+ /*
+ if (fullscreen)
+ {
+ DEVMODE dmScreenSettings;
+ // If full screen set the screen to maximum size of the users desktop and 32bit.
+ memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
+ dmScreenSettings.dmSize = sizeof(dmScreenSettings);
+ dmScreenSettings.dmPelsWidth = (unsigned long)width;
+ dmScreenSettings.dmPelsHeight = (unsigned long)height;
+ dmScreenSettings.dmBitsPerPel = 32;
+ dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+ // Change the display settings to full screen.
+ ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
+
+ // Set the position of the window to the top left corner.
+ posX = posY = 0;
+ }
+ */
+ // gIsFullscreen = fullscreen;
+
+ fHWnd = CreateWindow(gSZWindowClass, nullptr, WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, fHInstance, nullptr);
+ if (!fHWnd)
+ {
+ return false;
+ }
+
+ SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
+
+ return true;
+}
+
+static Window::Key get_key(WPARAM vk) {
+ static const struct {
+ WPARAM fVK;
+ Window::Key fKey;
+ } gPair[] = {
+ { VK_BACK, Window::kBack_Key },
+ { VK_CLEAR, Window::kBack_Key },
+ { VK_RETURN, Window::kOK_Key },
+ { VK_UP, Window::kUp_Key },
+ { VK_DOWN, Window::kDown_Key },
+ { VK_LEFT, Window::kLeft_Key },
+ { VK_RIGHT, Window::kRight_Key }
+ };
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+ if (gPair[i].fVK == vk) {
+ return gPair[i].fKey;
+ }
+ }
+ return Window::kNONE_Key;
+}
+
+static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
+ uint32_t modifiers = 0;
+
+ switch (message) {
+ case WM_UNICHAR:
+ case WM_CHAR:
+ if (0 == (lParam & (1 << 30))) {
+ modifiers |= Window::kFirstPress_ModifierKey;
+ }
+ if (lParam & (1 << 29)) {
+ modifiers |= Window::kOption_ModifierKey;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ if (0 == (lParam & (1 << 30))) {
+ modifiers |= Window::kFirstPress_ModifierKey;
+ }
+ if (lParam & (1 << 29)) {
+ modifiers |= Window::kOption_ModifierKey;
+ }
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ if (lParam & (1 << 29)) {
+ modifiers |= Window::kOption_ModifierKey;
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_MOUSEMOVE:
+ if (wParam & MK_CONTROL) {
+ modifiers |= Window::kControl_ModifierKey;
+ }
+ if (wParam & MK_SHIFT) {
+ modifiers |= Window::kShift_ModifierKey;
+ }
+ }
+
+ return modifiers;
+}
+
+LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ PAINTSTRUCT ps;
+ HDC hdc;
+
+ Window_win* window = (Window_win*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+
+ bool eventHandled = false;
+
+ switch (message) {
+ case WM_PAINT:
+ hdc = BeginPaint(hWnd, &ps);
+ window->onPaint();
+ EndPaint(hWnd, &ps);
+ eventHandled = true;
+ break;
+
+ case WM_CLOSE:
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ eventHandled = true;
+ break;
+
+ case WM_ACTIVATE:
+ // disable/enable rendering here, depending on wParam != WA_INACTIVE
+ break;
+
+ case WM_SIZE:
+ window->onResize(LOWORD(lParam), HIWORD(lParam));
+ eventHandled = true;
+ break;
+
+ case WM_UNICHAR:
+ eventHandled = window->onChar((SkUnichar)wParam,
+ get_modifiers(message, wParam, lParam));
+ break;
+
+ case WM_CHAR: {
+ const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
+ eventHandled = window->onChar(SkUTF16_NextUnichar(&c),
+ get_modifiers(message, wParam, lParam));
+ } break;
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ eventHandled = window->onKey(get_key(wParam), Window::kDown_InputState,
+ get_modifiers(message, wParam, lParam));
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ eventHandled = window->onKey(get_key(wParam), Window::kUp_InputState,
+ get_modifiers(message, wParam, lParam));
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP: {
+ int xPos = GET_X_LPARAM(lParam);
+ int yPos = GET_Y_LPARAM(lParam);
+
+ //if (!gIsFullscreen)
+ //{
+ // RECT rc = { 0, 0, 640, 480 };
+ // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
+ // xPos -= rc.left;
+ // yPos -= rc.top;
+ //}
+
+ Window::InputState istate = ((wParam & MK_LBUTTON) != 0) ? Window::kDown_InputState
+ : Window::kUp_InputState;
+
+ eventHandled = window->onMouse(xPos, yPos, istate,
+ get_modifiers(message, wParam, lParam));
+ } break;
+
+ case WM_MOUSEMOVE:
+ // only track if left button is down
+ if ((wParam & MK_LBUTTON) != 0) {
+ int xPos = GET_X_LPARAM(lParam);
+ int yPos = GET_Y_LPARAM(lParam);
+
+ //if (!gIsFullscreen)
+ //{
+ // RECT rc = { 0, 0, 640, 480 };
+ // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
+ // xPos -= rc.left;
+ // yPos -= rc.top;
+ //}
+
+ eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
+ get_modifiers(message, wParam, lParam));
+ }
+ break;
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ return eventHandled ? 0 : 1;
+}
+
+void Window_win::setTitle(const char* title) {
+ SetWindowTextA(fHWnd, title);
+}
+
+void Window_win::show() {
+ ShowWindow(fHWnd, SW_SHOW);
+}
+
+
+bool Window_win::attach(BackEndType attachType, int msaaSampleCount) {
+ if (kVulkan_BackendType != attachType) {
+ return false;
+ }
+
+ ContextPlatformData_win platformData;
+ platformData.fHInstance = fHInstance;
+ platformData.fHWnd = fHWnd;
+
+ fTestContext = VulkanTestContext::Create((void*)&platformData, msaaSampleCount);
+
+ return (SkToBool(fTestContext));
+}
+
+void Window_win::inval() {
+ InvalidateRect(fHWnd, nullptr, false);
+}
+
+} // namespace sk_app
--- /dev/null
+/*
+* 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_win_DEFINED
+#define Window_win_DEFINED
+
+#include <windows.h>
+#include "../Window.h"
+
+namespace sk_app {
+
+class Window_win : public Window {
+public:
+ Window_win() : Window() {}
+ ~Window_win() override {}
+
+ bool init(HINSTANCE instance);
+
+ void setTitle(const char*) override;
+ void show() override;
+
+ bool attach(BackEndType attachType, int msaaSampleCount) override;
+
+ void inval() override;
+
+private:
+ HINSTANCE fHInstance;
+ HWND fHWnd;
+};
+
+} // namespace sk_app
+
+#endif
--- /dev/null
+/*
+* 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 <windows.h>
+#include <tchar.h>
+
+#include "SkTypes.h"
+#include "Timer.h"
+#include "Window_win.h"
+#include "../Application.h"
+
+using sk_app::Application;
+
+static char* tchar_to_utf8(const TCHAR* str) {
+#ifdef _UNICODE
+ int size = WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), NULL, 0, NULL, NULL);
+ char* str8 = (char*)sk_malloc_throw(size + 1);
+ WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), str8, size, NULL, NULL);
+ str8[size] = '\0';
+ return str8;
+#else
+ return _strdup(str);
+#endif
+}
+
+static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
+
+// This file can work with GUI or CONSOLE subsystem types since we define _tWinMain and main().
+
+static int main_common(HINSTANCE hInstance, int show, int argc, char**argv);
+
+int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
+ int nCmdShow) {
+
+ // convert from lpCmdLine to argc, argv.
+ char* argv[4096];
+ int argc = 0;
+ TCHAR exename[1024], *next;
+ int exenameLen = GetModuleFileName(NULL, exename, SK_ARRAY_COUNT(exename));
+ // we're ignoring the possibility that the exe name exceeds the exename buffer
+ (void)exenameLen;
+ argv[argc++] = tchar_to_utf8(exename);
+ TCHAR* arg = _tcstok_s(lpCmdLine, _T(" "), &next);
+ while (arg != NULL) {
+ argv[argc++] = tchar_to_utf8(arg);
+ arg = _tcstok_s(NULL, _T(" "), &next);
+ }
+ int result = main_common(hInstance, nCmdShow, argc, argv);
+ for (int i = 0; i < argc; ++i) {
+ sk_free(argv[i]);
+ }
+ return result;
+}
+
+int main(int argc, char**argv) {
+ return main_common(GetModuleHandle(NULL), SW_SHOW, argc, argv);
+}
+
+static int main_common(HINSTANCE hInstance, int show, int argc, char**argv) {
+
+ Application* app = Application::Create(argc, argv, (void*)hInstance);
+
+ MSG msg = { 0 };
+
+ double currentTime = 0.0;
+ double previousTime = 0.0;
+
+ // Main message loop
+ while (WM_QUIT != msg.message) {
+ if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ } else {
+ previousTime = currentTime;
+ currentTime = now_ms();
+ app->onIdle(currentTime - previousTime);
+ }
+ }
+
+ delete app;
+
+ return (int)msg.wParam;
+}
+++ /dev/null
-/*
-* 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 Application_DEFINED
-#define Application_DEFINED
-
-class Application {
-public:
- static Application* Create(int argc, char** argv, void* platformData);
-
- virtual ~Application() {}
-
- virtual void onIdle(double ms) = 0;
-};
-
-#endif
+++ /dev/null
-
-/*
- * 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 "GrContext.h"
-#include "SkSurface.h"
-#include "VulkanTestContext.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
-#include "vk/GrVkTypes.h"
-
-#ifdef VK_USE_PLATFORM_WIN32_KHR
-// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
-#undef CreateSemaphore
-#endif
-
-#define GET_PROC(F) f ## F = (PFN_vk ## F) vkGetInstanceProcAddr(instance, "vk" #F)
-#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) vkGetDeviceProcAddr(device, "vk" #F)
-
-VulkanTestContext::VulkanTestContext(void* platformData, int msaaSampleCount)
- : fSurface(VK_NULL_HANDLE)
- , fSwapchain(VK_NULL_HANDLE)
- , fCommandPool(VK_NULL_HANDLE)
- , fBackbuffers(nullptr) {
-
- // any config code here (particularly for msaa)?
-
- this->initializeContext(platformData);
-}
-
-void VulkanTestContext::initializeContext(void* platformData) {
-
- fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent));
- if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
- !(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) {
- fBackendContext.reset(nullptr);
- return;
- }
-
- VkInstance instance = fBackendContext->fInstance;
- VkDevice device = fBackendContext->fDevice;
- GET_PROC(DestroySurfaceKHR);
- GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
- GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
- GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
- GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
- GET_DEV_PROC(CreateSwapchainKHR);
- GET_DEV_PROC(DestroySwapchainKHR);
- GET_DEV_PROC(GetSwapchainImagesKHR);
- GET_DEV_PROC(AcquireNextImageKHR);
- GET_DEV_PROC(QueuePresentKHR);
-
- fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext)fBackendContext.get());
-
- fSurface = createVkSurface(instance, platformData);
- if (VK_NULL_HANDLE == fSurface) {
- fBackendContext.reset(nullptr);
- return;
- }
-
- VkBool32 supported;
- VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fBackendContext->fPhysicalDevice,
- fPresentQueueIndex, fSurface,
- &supported);
- if (VK_SUCCESS != res) {
- this->destroyContext();
- return;
- }
-
- if (!this->createSwapchain(-1, -1)) {
- this->destroyContext();
- return;
- }
-
- // create presentQueue
- vkGetDeviceQueue(fBackendContext->fDevice, fPresentQueueIndex, 0, &fPresentQueue);
-}
-
-bool VulkanTestContext::createSwapchain(uint32_t width, uint32_t height)
-{
- // check for capabilities
- VkSurfaceCapabilitiesKHR caps;
- VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fBackendContext->fPhysicalDevice,
- fSurface, &caps);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t surfaceFormatCount;
- res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
- &surfaceFormatCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
- VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
- res = fGetPhysicalDeviceSurfaceFormatsKHR(fBackendContext->fPhysicalDevice, fSurface,
- &surfaceFormatCount, surfaceFormats);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- uint32_t presentModeCount;
- res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
- &presentModeCount, nullptr);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
- VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
- res = fGetPhysicalDeviceSurfacePresentModesKHR(fBackendContext->fPhysicalDevice, fSurface,
- &presentModeCount, presentModes);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- VkExtent2D extent = caps.currentExtent;
- // use the hints
- if (extent.width == (uint32_t)-1) {
- extent.width = width;
- extent.height = height;
- }
-
- // clamp width; to protect us from broken hints
- if (extent.width < caps.minImageExtent.width) {
- extent.width = caps.minImageExtent.width;
- } else if (extent.width > caps.maxImageExtent.width) {
- extent.width = caps.maxImageExtent.width;
- }
- // clamp height
- if (extent.height < caps.minImageExtent.height) {
- extent.height = caps.minImageExtent.height;
- } else if (extent.height > caps.maxImageExtent.height) {
- extent.height = caps.maxImageExtent.height;
- }
- fWidth = (int)extent.width;
- fHeight = (int)extent.height;
-
- uint32_t imageCount = caps.minImageCount + 2;
- if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
- // Application must settle for fewer images than desired:
- imageCount = caps.maxImageCount;
- }
-
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
- VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
- SkASSERT(caps.supportedTransforms & caps.currentTransform);
- SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
- VkCompositeAlphaFlagBitsKHR composite_alpha =
- (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
- VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
- VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-
- // Pick our surface format -- for now, the first one
- VkFormat surfaceFormat = surfaceFormats[0].format;
- VkColorSpaceKHR colorSpace = surfaceFormats[0].colorSpace;
-
- // If mailbox mode is available, use it, as it is the lowest-latency non-
- // tearing mode. If not, fall back to FIFO which is always available.
- VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
- for (uint32_t i = 0; i < presentModeCount; ++i) {
- // use mailbox
- if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
- mode = presentModes[i];
- break;
- }
- }
-
- VkSwapchainCreateInfoKHR swapchainCreateInfo;
- memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
- swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
- swapchainCreateInfo.surface = fSurface;
- swapchainCreateInfo.minImageCount = imageCount;
- swapchainCreateInfo.imageFormat = surfaceFormat;
- swapchainCreateInfo.imageColorSpace = colorSpace;
- swapchainCreateInfo.imageExtent = extent;
- swapchainCreateInfo.imageArrayLayers = 1;
- swapchainCreateInfo.imageUsage = usageFlags;
-
- uint32_t queueFamilies[] = { fBackendContext->fGraphicsQueueIndex, fPresentQueueIndex };
- if (fBackendContext->fGraphicsQueueIndex != fPresentQueueIndex) {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
- swapchainCreateInfo.queueFamilyIndexCount = 2;
- swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
- } else {
- swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
- swapchainCreateInfo.queueFamilyIndexCount = 0;
- swapchainCreateInfo.pQueueFamilyIndices = nullptr;
- }
-
- swapchainCreateInfo.preTransform = caps.currentTransform;;
- swapchainCreateInfo.compositeAlpha = composite_alpha;
- swapchainCreateInfo.presentMode = mode;
- swapchainCreateInfo.clipped = true;
- swapchainCreateInfo.oldSwapchain = fSwapchain;
-
- res = fCreateSwapchainKHR(fBackendContext->fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
- if (VK_SUCCESS != res) {
- return false;
- }
-
- // destroy the old swapchain
- if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
- GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
-
- this->destroyBuffers();
-
- fDestroySwapchainKHR(fBackendContext->fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
- }
-
- this->createBuffers(swapchainCreateInfo.imageFormat);
-
- return true;
-}
-
-void VulkanTestContext::createBuffers(VkFormat format) {
- GrVkFormatToPixelConfig(format, &fPixelConfig);
-
- fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, nullptr);
- SkASSERT(fImageCount);
- fImages = new VkImage[fImageCount];
- fGetSwapchainImagesKHR(fBackendContext->fDevice, fSwapchain, &fImageCount, fImages);
-
- // set up initial image layouts and create surfaces
- fImageLayouts = new VkImageLayout[fImageCount];
- fSurfaces = new sk_sp<SkSurface>[fImageCount];
- for (uint32_t i = 0; i < fImageCount; ++i) {
- fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
-
- GrBackendRenderTargetDesc desc;
- GrVkTextureInfo info;
- info.fImage = fImages[i];
- info.fAlloc = VK_NULL_HANDLE;
- info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info.fFormat = format;
- desc.fWidth = fWidth;
- desc.fHeight = fHeight;
- desc.fConfig = fPixelConfig;
- desc.fOrigin = kTopLeft_GrSurfaceOrigin;
- desc.fSampleCnt = 0;
- desc.fStencilBits = 0;
- desc.fRenderTargetHandle = (GrBackendObject) &info;
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
- fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(fContext, desc, &props);
- }
-
- // create the command pool for the command buffers
- if (VK_NULL_HANDLE == fCommandPool) {
- VkCommandPoolCreateInfo commandPoolInfo;
- memset(&commandPoolInfo, 0, sizeof(VkCommandPoolCreateInfo));
- commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- // this needs to be on the render queue
- commandPoolInfo.queueFamilyIndex = fBackendContext->fGraphicsQueueIndex;
- commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateCommandPool(fBackendContext->fDevice, &commandPoolInfo,
- nullptr, &fCommandPool));
- }
-
- // set up the backbuffers
- VkSemaphoreCreateInfo semaphoreInfo;
- memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.pNext = nullptr;
- semaphoreInfo.flags = 0;
- VkCommandBufferAllocateInfo commandBuffersInfo;
- memset(&commandBuffersInfo, 0, sizeof(VkCommandBufferAllocateInfo));
- commandBuffersInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
- commandBuffersInfo.pNext = nullptr;
- commandBuffersInfo.commandPool = fCommandPool;
- commandBuffersInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
- commandBuffersInfo.commandBufferCount = 2;
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.pNext = nullptr;
- fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
-
- // we create one additional backbuffer structure here, because we want to
- // give the command buffers they contain a chance to finish before we cycle back
- fBackbuffers = new BackbufferInfo[fImageCount + 1];
- for (uint32_t i = 0; i < fImageCount + 1; ++i) {
- fBackbuffers[i].fImageIndex = -1;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
- nullptr, &fBackbuffers[i].fAcquireSemaphore));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateSemaphore(fBackendContext->fDevice, &semaphoreInfo,
- nullptr, &fBackbuffers[i].fRenderSemaphore));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- AllocateCommandBuffers(fBackendContext->fDevice, &commandBuffersInfo,
- fBackbuffers[i].fTransitionCmdBuffers));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
- &fBackbuffers[i].fUsageFences[0]));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- CreateFence(fBackendContext->fDevice, &fenceInfo, nullptr,
- &fBackbuffers[i].fUsageFences[1]));
- }
- fCurrentBackbufferIndex = fImageCount;
-}
-
-void VulkanTestContext::destroyBuffers() {
-
- if (fBackbuffers) {
- for (uint32_t i = 0; i < fImageCount + 1; ++i) {
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- WaitForFences(fBackendContext->fDevice, 2,
- fBackbuffers[i].fUsageFences,
- true, UINT64_MAX));
- fBackbuffers[i].fImageIndex = -1;
- GR_VK_CALL(fBackendContext->fInterface,
- DestroySemaphore(fBackendContext->fDevice,
- fBackbuffers[i].fAcquireSemaphore,
- nullptr));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroySemaphore(fBackendContext->fDevice,
- fBackbuffers[i].fRenderSemaphore,
- nullptr));
- GR_VK_CALL(fBackendContext->fInterface,
- FreeCommandBuffers(fBackendContext->fDevice, fCommandPool, 2,
- fBackbuffers[i].fTransitionCmdBuffers));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[0], 0));
- GR_VK_CALL(fBackendContext->fInterface,
- DestroyFence(fBackendContext->fDevice, fBackbuffers[i].fUsageFences[1], 0));
- }
- }
-
- delete[] fBackbuffers;
- fBackbuffers = nullptr;
-
- delete[] fSurfaces;
- fSurfaces = nullptr;
- delete[] fImageLayouts;
- fImageLayouts = nullptr;
- delete[] fImages;
- fImages = nullptr;
-}
-
-VulkanTestContext::~VulkanTestContext() {
- this->destroyContext();
-}
-
-void VulkanTestContext::destroyContext() {
- if (!fBackendContext.get()) {
- return;
- }
-
- GR_VK_CALL(fBackendContext->fInterface, DeviceWaitIdle(fBackendContext->fDevice));
-
- this->destroyBuffers();
-
- if (VK_NULL_HANDLE != fCommandPool) {
- GR_VK_CALL(fBackendContext->fInterface, DestroyCommandPool(fBackendContext->fDevice,
- fCommandPool, nullptr));
- fCommandPool = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != fSwapchain) {
- fDestroySwapchainKHR(fBackendContext->fDevice, fSwapchain, nullptr);
- fSwapchain = VK_NULL_HANDLE;
- }
-
- if (VK_NULL_HANDLE != fSurface) {
- fDestroySurfaceKHR(fBackendContext->fInstance, fSurface, nullptr);
- fSurface = VK_NULL_HANDLE;
- }
-
- delete fContext;
-
- fBackendContext.reset(nullptr);
-}
-
-VulkanTestContext::BackbufferInfo* VulkanTestContext::getAvailableBackbuffer() {
- SkASSERT(fBackbuffers);
-
- ++fCurrentBackbufferIndex;
- if (fCurrentBackbufferIndex > fImageCount) {
- fCurrentBackbufferIndex = 0;
- }
-
- BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- WaitForFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences,
- true, UINT64_MAX));
- return backbuffer;
-}
-
-SkSurface* VulkanTestContext::getBackbufferSurface() {
- BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
- SkASSERT(backbuffer);
-
- // reset the fence
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetFences(fBackendContext->fDevice, 2, backbuffer->fUsageFences));
- // semaphores should be in unsignaled state
-
- // acquire the image
- VkResult res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
- backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->fImageIndex);
- if (VK_ERROR_SURFACE_LOST_KHR == res) {
- // need to figure out how to create a new vkSurface without the platformData*
- // maybe use attach somehow? but need a Window
- return nullptr;
- }
- if (VK_ERROR_OUT_OF_DATE_KHR == res) {
- // tear swapchain down and try again
- if (!this->createSwapchain(0, 0)) {
- return nullptr;
- }
-
- // acquire the image
- res = fAcquireNextImageKHR(fBackendContext->fDevice, fSwapchain, UINT64_MAX,
- backbuffer->fAcquireSemaphore, VK_NULL_HANDLE,
- &backbuffer->fImageIndex);
-
- if (VK_SUCCESS != res) {
- return nullptr;
- }
- }
-
- // set up layout transfer from initial to color attachment
- VkImageLayout layout = fImageLayouts[backbuffer->fImageIndex];
- VkPipelineStageFlags srcStageMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT :
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkAccessFlags srcAccessMask = (VK_IMAGE_LAYOUT_UNDEFINED == layout) ?
- 0 : VK_ACCESS_MEMORY_READ_BIT;
- VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
- fPresentQueueIndex, // srcQueueFamilyIndex
- fBackendContext->fGraphicsQueueIndex, // dstQueueFamilyIndex
- fImages[backbuffer->fImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
- };
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[0], 0));
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[0], &info));
-
- GR_VK_CALL(fBackendContext->fInterface,
- CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[0],
- srcStageMask, dstStageMask, 0,
- 0, nullptr,
- 0, nullptr,
- 1, &imageMemoryBarrier));
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- EndCommandBuffer(backbuffer->fTransitionCmdBuffers[0]));
-
- VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 1;
- submitInfo.pWaitSemaphores = &backbuffer->fAcquireSemaphore;
- submitInfo.pWaitDstStageMask = &waitDstStageFlags;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[0];
- submitInfo.signalSemaphoreCount = 0;
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
- backbuffer->fUsageFences[0]));
-
- return fSurfaces[backbuffer->fImageIndex].get();
-}
-
-
-void VulkanTestContext::swapBuffers() {
-
- BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
-
- VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
- VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
- VkAccessFlags srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- VkAccessFlags dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
-
- VkImageMemoryBarrier imageMemoryBarrier = {
- VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
- NULL, // pNext
- srcAccessMask, // outputMask
- dstAccessMask, // inputMask
- layout, // oldLayout
- VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, // newLayout
- fBackendContext->fGraphicsQueueIndex, // srcQueueFamilyIndex
- fPresentQueueIndex, // dstQueueFamilyIndex
- fImages[backbuffer->fImageIndex], // image
- { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 } // subresourceRange
- };
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- ResetCommandBuffer(backbuffer->fTransitionCmdBuffers[1], 0));
- VkCommandBufferBeginInfo info;
- memset(&info, 0, sizeof(VkCommandBufferBeginInfo));
- info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- info.flags = 0;
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- BeginCommandBuffer(backbuffer->fTransitionCmdBuffers[1], &info));
- GR_VK_CALL(fBackendContext->fInterface,
- CmdPipelineBarrier(backbuffer->fTransitionCmdBuffers[1],
- srcStageMask, dstStageMask, 0,
- 0, nullptr,
- 0, nullptr,
- 1, &imageMemoryBarrier));
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- EndCommandBuffer(backbuffer->fTransitionCmdBuffers[1]));
-
- fImageLayouts[backbuffer->fImageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- // insert the layout transfer into the queue and wait on the acquire
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitDstStageMask = 0;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &backbuffer->fTransitionCmdBuffers[1];
- submitInfo.signalSemaphoreCount = 1;
- submitInfo.pSignalSemaphores = &backbuffer->fRenderSemaphore;
-
- GR_VK_CALL_ERRCHECK(fBackendContext->fInterface,
- QueueSubmit(fBackendContext->fQueue, 1, &submitInfo,
- backbuffer->fUsageFences[1]));
-
- // Submit present operation to present queue
- const VkPresentInfoKHR presentInfo =
- {
- VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
- NULL, // pNext
- 1, // waitSemaphoreCount
- &backbuffer->fRenderSemaphore, // pWaitSemaphores
- 1, // swapchainCount
- &fSwapchain, // pSwapchains
- &backbuffer->fImageIndex, // pImageIndices
- NULL // pResults
- };
-
- fQueuePresentKHR(fPresentQueue, &presentInfo);
-
-}
+++ /dev/null
-
-/*
- * 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_DEFINED
-#define VulkanTestContext_DEFINED
-
-#ifdef SK_VULKAN
-
-#include "GrTypes.h"
-#include "vk/GrVkBackendContext.h"
-
-class SkSurface;
-class GrContext;
-
-class VulkanTestContext {
-public:
- ~VulkanTestContext();
-
- // each platform will have to implement these in its CPP file
- static VkSurfaceKHR createVkSurface(VkInstance, void* platformData);
- static bool canPresent(VkInstance, VkPhysicalDevice, uint32_t queueFamilyIndex);
-
- static VulkanTestContext* Create(void* platformData, int msaaSampleCount) {
- VulkanTestContext* ctx = new VulkanTestContext(platformData, msaaSampleCount);
- if (!ctx->isValid()) {
- delete ctx;
- return nullptr;
- }
- return ctx;
- }
-
- SkSurface* getBackbufferSurface();
- void swapBuffers();
-
- bool makeCurrent() { return true; }
-
- bool isValid() { return SkToBool(fBackendContext.get()); }
-
- void resize(uint32_t w, uint32_t h) {
- this->createSwapchain(w, h);
- }
-
- GrBackendContext getBackendContext() { return (GrBackendContext)fBackendContext.get(); }
-
-private:
- VulkanTestContext();
- VulkanTestContext(void*, int msaaSampleCount);
- void initializeContext(void*);
- void destroyContext();
-
- struct BackbufferInfo {
- uint32_t fImageIndex; // image this is associated with
- VkSemaphore fAcquireSemaphore; // we signal on this for acquisition of image
- VkSemaphore fRenderSemaphore; // we wait on this for rendering to be done
- VkCommandBuffer fTransitionCmdBuffers[2]; // to transition layout between present and render
- VkFence fUsageFences[2]; // used to ensure this data is no longer used on GPU
- };
-
- BackbufferInfo* getAvailableBackbuffer();
- bool createSwapchain(uint32_t width, uint32_t height);
- void createBuffers(VkFormat format);
- void destroyBuffers();
-
- SkAutoTUnref<const GrVkBackendContext> fBackendContext;
-
- // simple wrapper class that exists only to initialize a pointer to NULL
- template <typename FNPTR_TYPE> class VkPtr {
- public:
- VkPtr() : fPtr(NULL) {}
- VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }
- operator FNPTR_TYPE() const { return fPtr; }
- private:
- FNPTR_TYPE fPtr;
- };
-
- // WSI interface functions
- VkPtr<PFN_vkDestroySurfaceKHR> fDestroySurfaceKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceSupportKHR> fGetPhysicalDeviceSurfaceSupportKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR> fGetPhysicalDeviceSurfaceCapabilitiesKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR> fGetPhysicalDeviceSurfaceFormatsKHR;
- VkPtr<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR> fGetPhysicalDeviceSurfacePresentModesKHR;
-
- VkPtr<PFN_vkCreateSwapchainKHR> fCreateSwapchainKHR;
- VkPtr<PFN_vkDestroySwapchainKHR> fDestroySwapchainKHR;
- VkPtr<PFN_vkGetSwapchainImagesKHR> fGetSwapchainImagesKHR;
- VkPtr<PFN_vkAcquireNextImageKHR> fAcquireNextImageKHR;
- VkPtr<PFN_vkQueuePresentKHR> fQueuePresentKHR;
- VkPtr<PFN_vkCreateSharedSwapchainsKHR> fCreateSharedSwapchainsKHR;
-
- GrContext* fContext;
- VkSurfaceKHR fSurface;
- VkSwapchainKHR fSwapchain;
- uint32_t fPresentQueueIndex;
- VkQueue fPresentQueue;
- int fWidth;
- int fHeight;
- GrPixelConfig fPixelConfig;
-
- uint32_t fImageCount;
- VkImage* fImages; // images in the swapchain
- VkImageLayout* fImageLayouts; // layouts of these images when not color attachment
- sk_sp<SkSurface>* fSurfaces; // wrapped surface for those images
- VkCommandPool fCommandPool;
- BackbufferInfo* fBackbuffers;
- uint32_t fCurrentBackbufferIndex;
-};
-
-#endif // SK_VULKAN
-
-#endif
+++ /dev/null
-/*
-* 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.h"
-
-#include "SkSurface.h"
-#include "SkCanvas.h"
-#include "VulkanTestContext.h"
-
-static bool default_char_func(SkUnichar c, uint32_t modifiers, void* userData) {
- return false;
-}
-
-static bool default_key_func(Window::Key key, Window::InputState state, uint32_t modifiers,
- void* userData) {
- return false;
-}
-
-static bool default_mouse_func(int x, int y, Window::InputState state, uint32_t modifiers,
- void* userData) {
- return false;
-}
-
-static void default_paint_func(SkCanvas*, void* userData) {}
-
-Window::Window() : fCharFunc(default_char_func)
- , fKeyFunc(default_key_func)
- , fMouseFunc(default_mouse_func)
- , fPaintFunc(default_paint_func) {
-}
-
-void Window::detach() {
- delete fTestContext;
- fTestContext = nullptr;
-}
-
-bool Window::onChar(SkUnichar c, uint32_t modifiers) {
- return fCharFunc(c, modifiers, fCharUserData);
-}
-
-bool Window::onKey(Key key, InputState state, uint32_t modifiers) {
- return fKeyFunc(key, state, modifiers, fKeyUserData);
-}
-
-bool Window::onMouse(int x, int y, InputState state, uint32_t modifiers) {
- return fMouseFunc(x, y, state, modifiers, fMouseUserData);
-}
-
-void Window::onPaint() {
- SkSurface* backbuffer = fTestContext->getBackbufferSurface();
- if (backbuffer) {
- // draw into the canvas of this surface
- SkCanvas* canvas = backbuffer->getCanvas();
-
- fPaintFunc(canvas, fPaintUserData);
-
- canvas->flush();
-
- fTestContext->swapBuffers();
- } else {
- // try recreating testcontext
- }
-
-}
-
-void Window::onResize(uint32_t w, uint32_t h) {
- fWidth = w;
- fHeight = h;
- fTestContext->resize(w, h);
-}
+++ /dev/null
-/*
-* 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_DEFINED
-#define Window_DEFINED
-
-#include "SkTypes.h"
-#include "SkRect.h"
-
-class SkCanvas;
-class VulkanTestContext;
-
-class Window {
-public:
- static Window* CreateNativeWindow(void* platformData);
-
- virtual ~Window() {};
-
- virtual void setTitle(const char*) = 0;
- 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(); }
-
- enum BackEndType {
- kNativeGL_BackendType,
- kVulkan_BackendType
- };
-
- virtual bool attach(BackEndType attachType, int msaaSampleCount) = 0;
- void detach();
-
- // input handling
- enum Key {
- kNONE_Key, //corresponds to android's UNKNOWN
-
- kLeftSoftKey_Key,
- kRightSoftKey_Key,
-
- kHome_Key, //!< the home key - added to match android
- kBack_Key, //!< (CLR)
- kSend_Key, //!< the green (talk) key
- kEnd_Key, //!< the red key
-
- k0_Key,
- k1_Key,
- k2_Key,
- k3_Key,
- k4_Key,
- k5_Key,
- k6_Key,
- k7_Key,
- k8_Key,
- k9_Key,
- kStar_Key, //!< the * key
- kHash_Key, //!< the # key
-
- kUp_Key,
- kDown_Key,
- kLeft_Key,
- kRight_Key,
-
- kOK_Key, //!< the center key
-
- kVolUp_Key, //!< volume up - match android
- kVolDown_Key, //!< volume down - same
- kPower_Key, //!< power button - same
- kCamera_Key, //!< camera - same
-
- kLast_Key = kCamera_Key
- };
- static const int kKeyCount = kLast_Key + 1;
-
- enum ModifierKeys {
- kShift_ModifierKey = 1 << 0,
- kControl_ModifierKey = 1 << 1,
- kOption_ModifierKey = 1 << 2, // same as ALT
- kCommand_ModifierKey = 1 << 3,
- kFirstPress_ModifierKey = 1 << 4,
- };
-
- enum InputState {
- kDown_InputState,
- kUp_InputState,
- kMove_InputState // only valid for mouse
- };
-
- // return value of 'true' means 'I have handled this event'
- typedef bool(*OnCharFunc)(SkUnichar c, uint32_t modifiers, void* userData);
- typedef bool(*OnKeyFunc)(Key key, InputState state, uint32_t modifiers, void* userData);
- typedef bool(*OnMouseFunc)(int x, int y, InputState state, uint32_t modifiers, void* userData);
- typedef void(*OnPaintFunc)(SkCanvas*, void* userData);
-
- void registerCharFunc(OnCharFunc func, void* userData) {
- fCharFunc = func;
- fCharUserData = userData;
- }
-
- void registerKeyFunc(OnKeyFunc func, void* userData) {
- fKeyFunc = func;
- fKeyUserData = userData;
- }
-
- void registerMouseFunc(OnMouseFunc func, void* userData) {
- fMouseFunc = func;
- fMouseUserData = userData;
- }
-
- void registerPaintFunc(OnPaintFunc func, void* userData) {
- fPaintFunc = func;
- fPaintUserData = userData;
- }
-
- bool onChar(SkUnichar c, uint32_t modifiers);
- bool onKey(Key key, InputState state, uint32_t modifiers);
- bool onMouse(int x, int y, InputState state, uint32_t modifiers);
- void onPaint();
- void onResize(uint32_t width, uint32_t height);
-
- uint32_t width() { return fWidth; }
- uint32_t height() { return fHeight; }
-
-protected:
- Window();
-
- uint32_t fWidth;
- uint32_t fHeight;
-
- OnCharFunc fCharFunc;
- void* fCharUserData;
- OnKeyFunc fKeyFunc;
- void* fKeyUserData;
- OnMouseFunc fMouseFunc;
- void* fMouseUserData;
- OnPaintFunc fPaintFunc;
- void* fPaintUserData;
-
- VulkanTestContext* fTestContext;
-};
-
-
-#endif
+++ /dev/null
-
-/*
- * 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 "VulkanTestContext_android.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
-
-VkSurfaceKHR VulkanTestContext::createVkSurface(VkInstance instance, void* platformData) {
- static PFN_vkCreateAndroidSurfaceKHR createAndroidSurfaceKHR = nullptr;
- if (!createAndroidSurfaceKHR) {
- createAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)vkGetInstanceProcAddr(instance,
- "vkCreateAndroidSurfaceKHR");
- }
-
- if (!platformData) {
- return VK_NULL_HANDLE;
- }
- 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 = createAndroidSurfaceKHR(instance, &surfaceCreateInfo,
- nullptr, &surface);
- return (VK_SUCCESS == res) ? surface : VK_NULL_HANDLE;
-}
-
-bool VulkanTestContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
- uint32_t queueFamilyIndex) {
- return true;
-}
+++ /dev/null
-
-/*
- * 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
+++ /dev/null
-/*
-* 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) {
- 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;
-}
+++ /dev/null
-/*
-* 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) 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
+++ /dev/null
-/*
-* 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)
+++ /dev/null
-/*
-* Copyright 2016 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-/*
-* Copyright 2014 Google Inc.
-*
-* Use of this source code is governed by a BSD-style license that can be
-* found in the LICENSE file.
-*/
-
-#include "GMSlide.h"
-#include "SkCanvas.h"
-
-GMSlide::GMSlide(skiagm::GM* gm) : fGM(gm) {
- fName.printf("GM_%s", gm->getName());
-}
-
-GMSlide::~GMSlide() { delete fGM; }
-
-void GMSlide::draw(SkCanvas* canvas) {
- // Do we care about timing the draw of the background (once)?
- // Does the GM ever rely on drawBackground to lazily compute something?
- fGM->drawBackground(canvas);
- fGM->drawContent(canvas);
-}
-
-bool GMSlide::animate(const SkAnimTimer& timer) {
- return fGM->animate(timer);
-}
+++ /dev/null
-/*
-* 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 GMSlide_DEFINED
-#define GMSlide_DEFINED
-
-#include "Slide.h"
-#include "gm.h"
-
-class GMSlide : public Slide {
-public:
- GMSlide(skiagm::GM* gm);
- ~GMSlide() override;
-
- SkISize getDimensions() const override { return fGM->getISize(); }
-
- void draw(SkCanvas* canvas) override;
- bool animate(const SkAnimTimer&) override;
-
-private:
- skiagm::GM* fGM;
-};
-
-
-#endif
+++ /dev/null
-/*
-* 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 "SKPSlide.h"
-
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkOSFile.h"
-#include "SkStream.h"
-
-SKPSlide::SKPSlide(const SkString& name, const SkString& path) : fPath(path) {
- fName = name;
-}
-
-SKPSlide::~SKPSlide() {}
-
-void SKPSlide::draw(SkCanvas* canvas) {
- if (fPic.get()) {
- bool isOffset = SkToBool(fCullRect.left() | fCullRect.top());
- if (isOffset) {
- canvas->save();
- canvas->translate(SkIntToScalar(-fCullRect.left()), SkIntToScalar(-fCullRect.top()));
- }
-
- canvas->drawPicture(fPic.get());
-
- if (isOffset) {
- canvas->restore();
- }
- }
-}
-
-static sk_sp<SkPicture> read_picture(const char path[]) {
- SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(path));
- if (stream.get() == nullptr) {
- SkDebugf("Could not read %s.\n", path);
- return nullptr;
- }
-
- auto pic = SkPicture::MakeFromStream(stream.get());
- if (!pic) {
- SkDebugf("Could not read %s as an SkPicture.\n", path);
- }
- return pic;
-}
-
-void SKPSlide::load() {
- fPic = read_picture(fPath.c_str());
- fCullRect = fPic->cullRect().roundOut();
-}
-
-void SKPSlide::unload() {
- fPic.reset(nullptr);
-}
+++ /dev/null
-/*
-* 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 SKPSlide_DEFINED
-#define SKPSlide_DEFINED
-
-#include "Slide.h"
-#include "SkPicture.h"
-
-class SKPSlide : public Slide {
-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;
-
-private:
- SkString fPath;
- sk_sp<const SkPicture> fPic;
- SkIRect fCullRect;
-};
-
-#endif
+++ /dev/null
-/*
-* 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 Slide_DEFINED
-#define Slide_DEFINED
-
-#include "SkRefCnt.h"
-#include "SkSize.h"
-#include "SkString.h"
-
-class SkCanvas;
-class SkAnimTimer;
-
-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() {}
- virtual void unload() {}
-
- SkString getName() { return fName; }
-
-protected:
- SkString fName;
-};
-
-
-#endif
+++ /dev/null
-/*
-* 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 "VulkanViewer.h"
-
-#include "GMSlide.h"
-#include "SKPSlide.h"
-
-#include "SkCanvas.h"
-#include "SkCommonFlags.h"
-#include "SkOSFile.h"
-#include "SkRandom.h"
-#include "SkStream.h"
-
-Application* Application::Create(int argc, char** argv, void* platformData) {
- return new VulkanViewer(argc, argv, platformData);
-}
-
-static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
- void* userData) {
- VulkanViewer* vv = reinterpret_cast<VulkanViewer*>(userData);
-
- return vv->onKey(key, state, modifiers);
-}
-
-static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
- VulkanViewer* vv = reinterpret_cast<VulkanViewer*>(userData);
-
- return vv->onChar(c, modifiers);
-}
-
-static void on_paint_handler(SkCanvas* canvas, void* userData) {
- VulkanViewer* vv = reinterpret_cast<VulkanViewer*>(userData);
-
- return vv->onPaint(canvas);
-}
-
-DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
-DEFINE_string(key, "", "Space-separated key/value pairs to add to JSON identifying this builder.");
-DEFINE_string2(match, m, nullptr,
- "[~][^]substring[$] [...] of bench name to run.\n"
- "Multiple matches may be separated by spaces.\n"
- "~ causes a matching bench to always be skipped\n"
- "^ requires the start of the bench to match\n"
- "$ requires the end of the bench to match\n"
- "^ and $ requires an exact match\n"
- "If a bench does not match any list entry,\n"
- "it is skipped unless some list entry starts with ~");
-DEFINE_string(skps, "skps", "Directory to read skps from.");
-
-VulkanViewer::VulkanViewer(int argc, char** argv, void* platformData)
- : fCurrentMeasurement(0)
- , fDisplayStats(false)
- , fZoomCenterX(0.0f)
- , fZoomCenterY(0.0f)
- , fZoomLevel(0.0f)
- , fZoomScale(SK_Scalar1)
-{
- memset(fMeasurements, 0, sizeof(fMeasurements));
-
- SkDebugf("Command line arguments: ");
- for (int i = 1; i < argc; ++i) {
- SkDebugf("%s ", argv[i]);
- }
- SkDebugf("\n");
-
- SkCommandLineFlags::Parse(argc, argv);
-
- fWindow = Window::CreateNativeWindow(platformData);
- fWindow->attach(Window::kVulkan_BackendType, 0);
-
- // register callbacks
- fWindow->registerKeyFunc(on_key_handler, this);
- fWindow->registerCharFunc(on_char_handler, this);
- fWindow->registerPaintFunc(on_paint_handler, this);
-
- // set up slides
- this->initSlides();
-
- fAnimTimer.run();
-
- // set up first frame
- fCurrentSlide = 0;
- setupCurrentSlide(-1);
- updateMatrix();
-
- fWindow->show();
-}
-
-void VulkanViewer::initSlides() {
- const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
- while (gms) {
- SkAutoTDelete<skiagm::GM> gm(gms->factory()(nullptr));
-
- if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
- sk_sp<Slide> slide(new GMSlide(gm.release()));
- fSlides.push_back(slide);
- }
-
- gms = gms->next();
- }
-
- // reverse array
- for (int i = 0; i < fSlides.count()/2; ++i) {
- sk_sp<Slide> temp = fSlides[i];
- fSlides[i] = fSlides[fSlides.count() - i - 1];
- fSlides[fSlides.count() - i - 1] = temp;
- }
-
- // SKPs
- for (int i = 0; i < FLAGS_skps.count(); i++) {
- if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
- continue;
- }
-
- SkString path(FLAGS_skps[i]);
- sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
- if (slide) {
- fSlides.push_back(slide);
- }
- } else {
- SkOSFile::Iter it(FLAGS_skps[i], ".skp");
- SkString skpName;
- while (it.next(&skpName)) {
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
- continue;
- }
-
- SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
- sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
- if (slide) {
- fSlides.push_back(slide);
- }
- }
- }
- }
-}
-
-
-VulkanViewer::~VulkanViewer() {
- fWindow->detach();
- delete fWindow;
-}
-
-void VulkanViewer::setupCurrentSlide(int previousSlide) {
- SkString title("VulkanViewer: ");
- title.append(fSlides[fCurrentSlide]->getName());
- fSlides[fCurrentSlide]->load();
- if (previousSlide >= 0) {
- fSlides[previousSlide]->unload();
- }
- fWindow->setTitle(title.c_str());
- fWindow->inval();
-}
-
-#define MAX_ZOOM_LEVEL 8
-#define MIN_ZOOM_LEVEL -8
-
-void VulkanViewer::changeZoomLevel(float delta) {
- fZoomLevel += delta;
- if (fZoomLevel > 0) {
- fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
- fZoomScale = fZoomLevel + SK_Scalar1;
- } else if (fZoomLevel < 0) {
- fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
- fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
- } else {
- fZoomScale = SK_Scalar1;
- }
- this->updateMatrix();
-}
-
-void VulkanViewer::updateMatrix(){
- SkMatrix m;
- m.reset();
-
- if (fZoomLevel) {
- SkPoint center;
- //m = this->getLocalMatrix();//.invert(&m);
- m.mapXY(fZoomCenterX, fZoomCenterY, ¢er);
- SkScalar cx = center.fX;
- SkScalar cy = center.fY;
-
- m.setTranslate(-cx, -cy);
- m.postScale(fZoomScale, fZoomScale);
- m.postTranslate(cx, cy);
- }
-
- // TODO: add gesture support
- // Apply any gesture matrix
- //m.preConcat(fGesture.localM());
- //m.preConcat(fGesture.globalM());
-
- fLocalMatrix = m;
-}
-
-bool VulkanViewer::onKey(Window::Key key, Window::InputState state, uint32_t modifiers) {
- if (Window::kDown_InputState == state) {
- switch (key) {
- case Window::kRight_Key: {
- int previousSlide = fCurrentSlide;
- fCurrentSlide++;
- if (fCurrentSlide >= fSlides.count()) {
- fCurrentSlide = 0;
- }
- setupCurrentSlide(previousSlide);
- return true;
- }
-
- case Window::kLeft_Key: {
- int previousSlide = fCurrentSlide;
- fCurrentSlide--;
- if (fCurrentSlide < 0) {
- fCurrentSlide = fSlides.count() - 1;
- }
- SkString title("VulkanViewer: ");
- title.append(fSlides[fCurrentSlide]->getName());
- fWindow->setTitle(title.c_str());
- setupCurrentSlide(previousSlide);
- return true;
- }
-
- case Window::kUp_Key: {
- this->changeZoomLevel(1.f / 32.f);
- fWindow->inval();
- return true;
- }
-
- case Window::kDown_Key: {
- this->changeZoomLevel(-1.f / 32.f);
- fWindow->inval();
- return true;
- }
-
- default:
- break;
- }
- }
-
- return false;
-}
-
-bool VulkanViewer::onChar(SkUnichar c, uint32_t modifiers) {
- if ('s' == c) {
- fDisplayStats = !fDisplayStats;
- return true;
- }
-
- return false;
-}
-
-void VulkanViewer::onPaint(SkCanvas* canvas) {
-
- int count = canvas->save();
-
- 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);
-
- if (fDisplayStats) {
- drawStats(canvas);
- }
-}
-
-void VulkanViewer::drawStats(SkCanvas* canvas) {
- static const float kPixelPerMS = 2.0f;
- static const int kDisplayWidth = 130;
- static const int kDisplayHeight = 100;
- static const int kDisplayPadding = 10;
- static const int kGraphPadding = 3;
- static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
-
- SkISize canvasSize = canvas->getDeviceSize();
- SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
- SkIntToScalar(kDisplayPadding),
- SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
- 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);
- // draw the 16ms line
- paint.setColor(SK_ColorLTGRAY);
- canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
- rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
- paint.setColor(SK_ColorRED);
- paint.setStyle(SkPaint::kStroke_Style);
- canvas->drawRect(rect, paint);
-
- int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
- const int xStep = 2;
- const int startY = SkScalarTruncToInt(rect.fBottom);
- int i = fCurrentMeasurement;
- do {
- int endY = startY - (int)(fMeasurements[i] * kPixelPerMS + 0.5); // round to nearest value
- canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
- SkIntToScalar(x), SkIntToScalar(endY), paint);
- i++;
- i &= (kMeasurementCount - 1); // fast mod
- x += xStep;
- } while (i != fCurrentMeasurement);
-
- canvas->restore();
-}
-
-void VulkanViewer::onIdle(double ms) {
- // Record measurements
- fMeasurements[fCurrentMeasurement++] = ms;
- fCurrentMeasurement &= (kMeasurementCount - 1); // fast mod
- SkASSERT(fCurrentMeasurement < kMeasurementCount);
-
- fAnimTimer.updateTime();
- if (fSlides[fCurrentSlide]->animate(fAnimTimer) || fDisplayStats) {
- fWindow->inval();
- }
-}
+++ /dev/null
-/*
-* 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 VulkanViewer_DEFINED
-#define VulkanViewer_DEFINED
-
-#include "../Application.h"
-#include "../Window.h"
-#include "gm.h"
-#include "SkAnimTimer.h"
-#include "Slide.h"
-
-class SkCanvas;
-
-class VulkanViewer : public Application {
-public:
- VulkanViewer(int argc, char** argv, void* platformData);
- ~VulkanViewer() override;
-
- bool onKey(Window::Key key, Window::InputState state, uint32_t modifiers);
- bool onChar(SkUnichar, uint32_t modifiers);
- void onPaint(SkCanvas* canvas);
- void onIdle(double ms) override;
-
-private:
- void initSlides();
- void setupCurrentSlide(int previousSlide);
-
- void drawStats(SkCanvas* canvas);
-
- void changeZoomLevel(float delta);
- void updateMatrix();
-
- Window* fWindow;
-
- static const int kMeasurementCount = 64; // should be power of 2 for fast mod
- double fMeasurements[kMeasurementCount];
- int fCurrentMeasurement;
-
- SkAnimTimer fAnimTimer;
- SkTArray<sk_sp<Slide>> fSlides;
- int fCurrentSlide;
-
- bool fDisplayStats;
-
- // transform data
- SkMatrix fLocalMatrix;
- SkScalar fZoomCenterX;
- SkScalar fZoomCenterY;
- SkScalar fZoomLevel;
- SkScalar fZoomScale;
-
-};
-
-
-#endif
+++ /dev/null
-
-/*
- * 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 "VulkanTestContext_win.h"
-
-#include "vk/GrVkInterface.h"
-#include "vk/GrVkUtil.h"
-
-// Platform dependant call
-VkSurfaceKHR VulkanTestContext::createVkSurface(VkInstance instance, void* platformData) {
- static PFN_vkCreateWin32SurfaceKHR createWin32SurfaceKHR = nullptr;
- if (!createWin32SurfaceKHR) {
- createWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(instance,
- "vkCreateWin32SurfaceKHR");
- }
-
- if (!platformData) {
- return VK_NULL_HANDLE;
- }
- ContextPlatformData_win* winPlatformData =
- reinterpret_cast<ContextPlatformData_win*>(platformData);
- VkSurfaceKHR surface;
-
- VkWin32SurfaceCreateInfoKHR surfaceCreateInfo;
- memset(&surfaceCreateInfo, 0, sizeof(VkWin32SurfaceCreateInfoKHR));
- surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
- surfaceCreateInfo.pNext = nullptr;
- surfaceCreateInfo.flags = 0;
- surfaceCreateInfo.hinstance = winPlatformData->fHInstance;
- surfaceCreateInfo.hwnd = winPlatformData->fHWnd;
-
- VkResult res = createWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
- if (VK_SUCCESS != res) {
- return VK_NULL_HANDLE;
- }
-
- return surface;
-}
-
-// Platform dependant call
-bool VulkanTestContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
- uint32_t queueFamilyIndex) {
- static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
- getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
- if (!getPhysicalDeviceWin32PresentationSupportKHR) {
- getPhysicalDeviceWin32PresentationSupportKHR =
- (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) vkGetInstanceProcAddr(instance,
- "vkGetPhysicalDeviceWin32PresentationSupportKHR");
- }
-
- VkBool32 check = getPhysicalDeviceWin32PresentationSupportKHR(physDev, queueFamilyIndex);
- return (VK_FALSE != check);
-}
+++ /dev/null
-
-/*
- * 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_WIN_DEFINED
-#define VULKANTESTCONTEXT_WIN_DEFINED
-
-#ifdef SK_VULKAN
-
-#include <windows.h>
-#include "../VulkanTestContext.h"
-
-// for Windows
-struct ContextPlatformData_win {
- HINSTANCE fHInstance;
- HWND fHWnd;
-};
-
-#endif // SK_VULKAN
-
-#endif
+++ /dev/null
-/*
-* 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_win.h"
-
-#include <tchar.h>
-#include <windows.h>
-#include <windowsx.h>
-
-#include "SkUtils.h"
-#include "VulkanTestContext_win.h"
-
-Window* Window::CreateNativeWindow(void* platformData) {
- HINSTANCE hInstance = (HINSTANCE)platformData;
-
- Window_win* window = new Window_win();
- if (!window->init(hInstance)) {
- delete window;
- return nullptr;
- }
-
- return window;
-}
-
-LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-
-bool Window_win::init(HINSTANCE hInstance) {
- fHInstance = hInstance ? hInstance : GetModuleHandle(nullptr);
-
- WNDCLASSEX wcex;
- // The main window class name
- static const TCHAR gSZWindowClass[] = _T("SkiaApp");
-
- wcex.cbSize = sizeof(WNDCLASSEX);
-
- wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = fHInstance;
- wcex.hIcon = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);;
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wcex.lpszMenuName = nullptr;
- wcex.lpszClassName = gSZWindowClass;
- wcex.hIconSm = LoadIcon(fHInstance, (LPCTSTR)IDI_WINLOGO);;
-
- if (!RegisterClassEx(&wcex)) {
- return false;
- }
-
- /*
- if (fullscreen)
- {
- DEVMODE dmScreenSettings;
- // If full screen set the screen to maximum size of the users desktop and 32bit.
- memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
- dmScreenSettings.dmSize = sizeof(dmScreenSettings);
- dmScreenSettings.dmPelsWidth = (unsigned long)width;
- dmScreenSettings.dmPelsHeight = (unsigned long)height;
- dmScreenSettings.dmBitsPerPel = 32;
- dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-
- // Change the display settings to full screen.
- ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
-
- // Set the position of the window to the top left corner.
- posX = posY = 0;
- }
- */
- // gIsFullscreen = fullscreen;
-
- fHWnd = CreateWindow(gSZWindowClass, nullptr, WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, fHInstance, nullptr);
- if (!fHWnd)
- {
- return false;
- }
-
- SetWindowLongPtr(fHWnd, GWLP_USERDATA, (LONG_PTR)this);
-
- return true;
-}
-
-static Window::Key get_key(WPARAM vk) {
- static const struct {
- WPARAM fVK;
- Window::Key fKey;
- } gPair[] = {
- { VK_BACK, Window::kBack_Key },
- { VK_CLEAR, Window::kBack_Key },
- { VK_RETURN, Window::kOK_Key },
- { VK_UP, Window::kUp_Key },
- { VK_DOWN, Window::kDown_Key },
- { VK_LEFT, Window::kLeft_Key },
- { VK_RIGHT, Window::kRight_Key }
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
- if (gPair[i].fVK == vk) {
- return gPair[i].fKey;
- }
- }
- return Window::kNONE_Key;
-}
-
-static uint32_t get_modifiers(UINT message, WPARAM wParam, LPARAM lParam) {
- uint32_t modifiers = 0;
-
- switch (message) {
- case WM_UNICHAR:
- case WM_CHAR:
- if (0 == (lParam & (1 << 30))) {
- modifiers |= Window::kFirstPress_ModifierKey;
- }
- if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
- }
- break;
-
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- if (0 == (lParam & (1 << 30))) {
- modifiers |= Window::kFirstPress_ModifierKey;
- }
- if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
- }
- break;
-
- case WM_KEYUP:
- case WM_SYSKEYUP:
- if (lParam & (1 << 29)) {
- modifiers |= Window::kOption_ModifierKey;
- }
- break;
-
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MOUSEMOVE:
- if (wParam & MK_CONTROL) {
- modifiers |= Window::kControl_ModifierKey;
- }
- if (wParam & MK_SHIFT) {
- modifiers |= Window::kShift_ModifierKey;
- }
- }
-
- return modifiers;
-}
-
-LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- PAINTSTRUCT ps;
- HDC hdc;
-
- Window_win* window = (Window_win*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
-
- bool eventHandled = false;
-
- switch (message) {
- case WM_PAINT:
- hdc = BeginPaint(hWnd, &ps);
- window->onPaint();
- EndPaint(hWnd, &ps);
- eventHandled = true;
- break;
-
- case WM_CLOSE:
- case WM_DESTROY:
- PostQuitMessage(0);
- eventHandled = true;
- break;
-
- case WM_ACTIVATE:
- // disable/enable rendering here, depending on wParam != WA_INACTIVE
- break;
-
- case WM_SIZE:
- window->onResize(LOWORD(lParam), HIWORD(lParam));
- eventHandled = true;
- break;
-
- case WM_UNICHAR:
- eventHandled = window->onChar((SkUnichar)wParam,
- get_modifiers(message, wParam, lParam));
- break;
-
- case WM_CHAR: {
- const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
- eventHandled = window->onChar(SkUTF16_NextUnichar(&c),
- get_modifiers(message, wParam, lParam));
- } break;
-
- case WM_KEYDOWN:
- case WM_SYSKEYDOWN:
- eventHandled = window->onKey(get_key(wParam), Window::kDown_InputState,
- get_modifiers(message, wParam, lParam));
- break;
-
- case WM_KEYUP:
- case WM_SYSKEYUP:
- eventHandled = window->onKey(get_key(wParam), Window::kUp_InputState,
- get_modifiers(message, wParam, lParam));
- break;
-
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP: {
- int xPos = GET_X_LPARAM(lParam);
- int yPos = GET_Y_LPARAM(lParam);
-
- //if (!gIsFullscreen)
- //{
- // RECT rc = { 0, 0, 640, 480 };
- // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
- // xPos -= rc.left;
- // yPos -= rc.top;
- //}
-
- Window::InputState istate = ((wParam & MK_LBUTTON) != 0) ? Window::kDown_InputState
- : Window::kUp_InputState;
-
- eventHandled = window->onMouse(xPos, yPos, istate,
- get_modifiers(message, wParam, lParam));
- } break;
-
- case WM_MOUSEMOVE:
- // only track if left button is down
- if ((wParam & MK_LBUTTON) != 0) {
- int xPos = GET_X_LPARAM(lParam);
- int yPos = GET_Y_LPARAM(lParam);
-
- //if (!gIsFullscreen)
- //{
- // RECT rc = { 0, 0, 640, 480 };
- // AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
- // xPos -= rc.left;
- // yPos -= rc.top;
- //}
-
- eventHandled = window->onMouse(xPos, yPos, Window::kMove_InputState,
- get_modifiers(message, wParam, lParam));
- }
- break;
-
- default:
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
-
- return eventHandled ? 0 : 1;
-}
-
-void Window_win::setTitle(const char* title) {
- SetWindowTextA(fHWnd, title);
-}
-
-void Window_win::show() {
- ShowWindow(fHWnd, SW_SHOW);
-}
-
-
-bool Window_win::attach(BackEndType attachType, int msaaSampleCount) {
- if (kVulkan_BackendType != attachType) {
- return false;
- }
-
- ContextPlatformData_win platformData;
- platformData.fHInstance = fHInstance;
- platformData.fHWnd = fHWnd;
-
- fTestContext = VulkanTestContext::Create((void*)&platformData, msaaSampleCount);
-
- return (SkToBool(fTestContext));
-}
-
-void Window_win::inval() {
- InvalidateRect(fHWnd, nullptr, false);
-}
+++ /dev/null
-/*
-* 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_win_DEFINED
-#define Window_win_DEFINED
-
-#include <windows.h>
-#include "../Window.h"
-
-class Window_win : public Window {
-public:
- Window_win() : Window() {}
- ~Window_win() override {}
-
- bool init(HINSTANCE instance);
-
- void setTitle(const char*) override;
- void show() override;
-
- bool attach(BackEndType attachType, int msaaSampleCount) override;
-
- void inval() override;
-
-private:
- HINSTANCE fHInstance;
- HWND fHWnd;
-};
-
-#endif
+++ /dev/null
-/*
-* 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 <windows.h>
-#include <tchar.h>
-
-#include "SkTypes.h"
-#include "Timer.h"
-#include "Window_win.h"
-#include "../Application.h"
-
-static char* tchar_to_utf8(const TCHAR* str) {
-#ifdef _UNICODE
- int size = WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), NULL, 0, NULL, NULL);
- char* str8 = (char*)sk_malloc_throw(size + 1);
- WideCharToMultiByte(CP_UTF8, 0, str, wcslen(str), str8, size, NULL, NULL);
- str8[size] = '\0';
- return str8;
-#else
- return _strdup(str);
-#endif
-}
-
-static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
-
-// This file can work with GUI or CONSOLE subsystem types since we define _tWinMain and main().
-
-static int main_common(HINSTANCE hInstance, int show, int argc, char**argv);
-
-int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine,
- int nCmdShow) {
-
- // convert from lpCmdLine to argc, argv.
- char* argv[4096];
- int argc = 0;
- TCHAR exename[1024], *next;
- int exenameLen = GetModuleFileName(NULL, exename, SK_ARRAY_COUNT(exename));
- // we're ignoring the possibility that the exe name exceeds the exename buffer
- (void)exenameLen;
- argv[argc++] = tchar_to_utf8(exename);
- TCHAR* arg = _tcstok_s(lpCmdLine, _T(" "), &next);
- while (arg != NULL) {
- argv[argc++] = tchar_to_utf8(arg);
- arg = _tcstok_s(NULL, _T(" "), &next);
- }
- int result = main_common(hInstance, nCmdShow, argc, argv);
- for (int i = 0; i < argc; ++i) {
- sk_free(argv[i]);
- }
- return result;
-}
-
-int main(int argc, char**argv) {
- return main_common(GetModuleHandle(NULL), SW_SHOW, argc, argv);
-}
-
-static int main_common(HINSTANCE hInstance, int show, int argc, char**argv) {
-
- Application* app = Application::Create(argc, argv, (void*)hInstance);
-
- MSG msg = { 0 };
-
- double currentTime = 0.0;
- double previousTime = 0.0;
-
- // Main message loop
- while (WM_QUIT != msg.message) {
- if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- } else {
- previousTime = currentTime;
- currentTime = now_ms();
- app->onIdle(currentTime - previousTime);
- }
- }
-
- delete app;
-
- return (int)msg.wParam;
-}