Add Xlib support to viewer
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=1999213002 Review-Url: https://codereview.chromium.org/1999213002
This commit is contained in:
parent
50134ccafd
commit
1d15596200
@ -25,11 +25,13 @@
|
||||
'../src/gpu',
|
||||
'../src/images',
|
||||
'../src/image',
|
||||
'../src/views/unix',
|
||||
'../tools/timer',
|
||||
],
|
||||
'sources': [
|
||||
'../gm/gm.cpp',
|
||||
'../src/views/SkTouchGesture.cpp',
|
||||
'../src/views/unix/keysym2ucs.c',
|
||||
'<!@(python find.py ../tools/viewer "*.cpp")',
|
||||
],
|
||||
'dependencies': [
|
||||
@ -56,10 +58,23 @@
|
||||
],
|
||||
},
|
||||
}],
|
||||
[ 'skia_os == "linux"', {
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
'-lX11-xcb',
|
||||
],
|
||||
},
|
||||
}],
|
||||
['skia_os != "android"', {
|
||||
'sources/': [ ['exclude', '_android.(h|cpp)$'],
|
||||
],
|
||||
}],
|
||||
['skia_os != "linux"', {
|
||||
'sources/': [
|
||||
['exclude', '_unix.(h|cpp)$'],
|
||||
['exclude', 'keysym2ucs.c'],
|
||||
],
|
||||
}],
|
||||
['skia_os != "win"', {
|
||||
'sources/': [ ['exclude', '_win.(h|cpp)$'],
|
||||
],
|
||||
|
@ -25,7 +25,7 @@ enum GrVkExtensionFlags {
|
||||
kKHR_swapchain_GrVkExtensionFlag = 0x0008,
|
||||
kKHR_win32_surface_GrVkExtensionFlag = 0x0010,
|
||||
kKHR_android_surface_GrVkExtensionFlag = 0x0020,
|
||||
kKHR_xlib_surface_GrVkExtensionFlag = 0x0040,
|
||||
kKHR_xcb_surface_GrVkExtensionFlag = 0x0040,
|
||||
};
|
||||
|
||||
enum GrVkFeatureFlags {
|
||||
@ -55,7 +55,9 @@ struct GrVkBackendContext : public SkRefCnt {
|
||||
// If presentQueueIndex is non-NULL, will try to set up presentQueue as part of device
|
||||
// creation. canPresent() is a device-dependent function.
|
||||
static const GrVkBackendContext* Create(uint32_t* presentQueueIndex = nullptr,
|
||||
bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex) = nullptr);
|
||||
bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex,
|
||||
void* platformData) = nullptr,
|
||||
void* platformData = nullptr);
|
||||
|
||||
~GrVkBackendContext() override;
|
||||
};
|
||||
|
@ -14,7 +14,7 @@
|
||||
#elif defined(SK_BUILD_FOR_ANDROID)
|
||||
# define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#elif defined(SK_BUILD_FOR_UNIX)
|
||||
# define VK_USE_PLATFORM_XLIB_KHR
|
||||
# define VK_USE_PLATFORM_XCB_KHR
|
||||
#endif
|
||||
|
||||
#if defined(Bool) || defined(Status) || defined(True) || defined(False)
|
||||
@ -23,19 +23,4 @@
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
|
||||
// Xlib.h may define these macros with common names (Grrr)
|
||||
#ifdef Bool
|
||||
# undef Bool
|
||||
#endif
|
||||
#ifdef Status
|
||||
# undef Status
|
||||
#endif
|
||||
#ifdef True
|
||||
# undef True
|
||||
#endif
|
||||
#ifdef False
|
||||
# undef False
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -40,7 +40,9 @@ const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
|
||||
|
||||
// Create the base Vulkan objects needed by the GrVkGpu object
|
||||
const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
|
||||
bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex)) {
|
||||
bool(*canPresent)(VkInstance, VkPhysicalDevice, uint32_t queueIndex,
|
||||
void* platformData),
|
||||
void* platformData) {
|
||||
VkPhysicalDevice physDev;
|
||||
VkDevice device;
|
||||
VkInstance inst;
|
||||
@ -91,11 +93,11 @@ const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndex
|
||||
if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
|
||||
instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
|
||||
extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
|
||||
}
|
||||
}
|
||||
#elif SK_BUILD_FOR_UNIX
|
||||
if (extensions.hasInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) {
|
||||
instanceExtensionNames.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
extensionFlags |= kKHR_xlib_surface_GrVkExtensionFlag;
|
||||
if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
|
||||
instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||
extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -159,7 +161,7 @@ const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndex
|
||||
uint32_t presentQueueIndex = graphicsQueueIndex;
|
||||
if (presentQueueIndexPtr && canPresent) {
|
||||
for (uint32_t i = 0; i < queueCount; i++) {
|
||||
if (canPresent(inst, physDev, i)) {
|
||||
if (canPresent(inst, physDev, i, platformData)) {
|
||||
presentQueueIndex = i;
|
||||
break;
|
||||
}
|
||||
|
@ -41,8 +41,9 @@ VulkanWindowContext::VulkanWindowContext(void* platformData, const DisplayParams
|
||||
}
|
||||
|
||||
void VulkanWindowContext::initializeContext(void* platformData, const DisplayParams& params) {
|
||||
fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent,
|
||||
platformData));
|
||||
|
||||
fBackendContext.reset(GrVkBackendContext::Create(&fPresentQueueIndex, canPresent));
|
||||
if (!(fBackendContext->fExtensions & kKHR_surface_GrVkExtensionFlag) ||
|
||||
!(fBackendContext->fExtensions & kKHR_swapchain_GrVkExtensionFlag)) {
|
||||
fBackendContext.reset(nullptr);
|
||||
@ -147,6 +148,7 @@ bool VulkanWindowContext::createSwapchain(uint32_t width, uint32_t height,
|
||||
} else if (extent.height > caps.maxImageExtent.height) {
|
||||
extent.height = caps.maxImageExtent.height;
|
||||
}
|
||||
|
||||
fWidth = (int)extent.width;
|
||||
fHeight = (int)extent.height;
|
||||
|
||||
|
@ -23,7 +23,8 @@ public:
|
||||
|
||||
// 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 bool canPresent(VkInstance, VkPhysicalDevice, uint32_t queueFamilyIndex,
|
||||
void* platformData);
|
||||
|
||||
static VulkanWindowContext* Create(void* platformData, const DisplayParams& params) {
|
||||
VulkanWindowContext* ctx = new VulkanWindowContext(platformData, params);
|
||||
@ -99,8 +100,6 @@ private:
|
||||
VkSwapchainKHR fSwapchain;
|
||||
uint32_t fPresentQueueIndex;
|
||||
VkQueue fPresentQueue;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
|
||||
uint32_t fImageCount;
|
||||
VkImage* fImages; // images in the swapchain
|
||||
|
@ -40,7 +40,7 @@ VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* pla
|
||||
}
|
||||
|
||||
bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
|
||||
uint32_t queueFamilyIndex) {
|
||||
uint32_t queueFamilyIndex, void*) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
74
tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
Normal file
74
tools/viewer/sk_app/unix/VulkanWindowContext_unix.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
/*
|
||||
* 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 "../VulkanWindowContext.h"
|
||||
#include "Window_unix.h"
|
||||
|
||||
#include "vk/GrVkInterface.h"
|
||||
#include "vk/GrVkUtil.h"
|
||||
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
// Platform dependant call
|
||||
VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* platformData) {
|
||||
static PFN_vkCreateXcbSurfaceKHR createXcbSurfaceKHR = nullptr;
|
||||
if (!createXcbSurfaceKHR) {
|
||||
createXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) vkGetInstanceProcAddr(instance,
|
||||
"vkCreateXcbSurfaceKHR");
|
||||
}
|
||||
|
||||
if (!platformData) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
ContextPlatformData_unix* unixPlatformData =
|
||||
reinterpret_cast<ContextPlatformData_unix*>(platformData);
|
||||
|
||||
|
||||
VkSurfaceKHR surface;
|
||||
|
||||
VkXcbSurfaceCreateInfoKHR surfaceCreateInfo;
|
||||
memset(&surfaceCreateInfo, 0, sizeof(VkXcbSurfaceCreateInfoKHR));
|
||||
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
||||
surfaceCreateInfo.pNext = nullptr;
|
||||
surfaceCreateInfo.flags = 0;
|
||||
surfaceCreateInfo.connection = XGetXCBConnection(unixPlatformData->fDisplay);
|
||||
surfaceCreateInfo.window = unixPlatformData->fHWnd;
|
||||
|
||||
VkResult res = createXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
|
||||
if (VK_SUCCESS != res) {
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
// Platform dependant call
|
||||
bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
|
||||
uint32_t queueFamilyIndex, void* platformData) {
|
||||
static PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR
|
||||
getPhysicalDeviceXcbPresentationSupportKHR = nullptr;
|
||||
if (!getPhysicalDeviceXcbPresentationSupportKHR) {
|
||||
getPhysicalDeviceXcbPresentationSupportKHR =
|
||||
(PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) vkGetInstanceProcAddr(instance,
|
||||
"vkGetPhysicalDeviceXcbPresentationSupportKHR");
|
||||
}
|
||||
|
||||
ContextPlatformData_unix* unixPlatformData =
|
||||
reinterpret_cast<ContextPlatformData_unix*>(platformData);
|
||||
|
||||
Display* display = unixPlatformData->fDisplay;
|
||||
VkBool32 check = getPhysicalDeviceXcbPresentationSupportKHR(physDev,
|
||||
queueFamilyIndex,
|
||||
XGetXCBConnection(display),
|
||||
unixPlatformData->fVisualID);
|
||||
return (VK_FALSE != check);
|
||||
}
|
||||
|
||||
} // namespace sk_app
|
221
tools/viewer/sk_app/unix/Window_unix.cpp
Normal file
221
tools/viewer/sk_app/unix/Window_unix.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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 <tchar.h>
|
||||
|
||||
#include "SkUtils.h"
|
||||
#include "Timer.h"
|
||||
#include "../VulkanWindowContext.h"
|
||||
#include "Window_unix.h"
|
||||
|
||||
extern "C" {
|
||||
#include "keysym2ucs.h"
|
||||
}
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/XKBlib.h>
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
SkTDynamicHash<Window_unix, XWindow> Window_unix::gWindowMap;
|
||||
|
||||
Window* Window::CreateNativeWindow(void* platformData) {
|
||||
Display* display = (Display*)platformData;
|
||||
|
||||
Window_unix* window = new Window_unix();
|
||||
if (!window->init(display)) {
|
||||
delete window;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
bool Window_unix::init(Display* display) {
|
||||
fDisplay = display;
|
||||
|
||||
fWidth = 1280;
|
||||
fHeight = 960;
|
||||
fHWnd = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, fWidth, fHeight,
|
||||
0, BlackPixel(display, DefaultScreen(display)),
|
||||
BlackPixel(display, DefaultScreen(display)));
|
||||
|
||||
if (!fHWnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// choose the events we care about
|
||||
XSelectInput(display, fHWnd,
|
||||
ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask |
|
||||
PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
|
||||
|
||||
// set up to catch window delete message
|
||||
fWmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(display, fHWnd, &fWmDeleteMessage, 1);
|
||||
|
||||
// add to hashtable of windows
|
||||
gWindowMap.add(this);
|
||||
|
||||
// init event variables
|
||||
fPendingPaint = false;
|
||||
fPendingResize = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static Window::Key get_key(KeySym keysym) {
|
||||
static const struct {
|
||||
KeySym fXK;
|
||||
Window::Key fKey;
|
||||
} gPair[] = {
|
||||
{ XK_BackSpace, Window::Key::kBack },
|
||||
{ XK_Clear, Window::Key::kBack },
|
||||
{ XK_Return, Window::Key::kOK },
|
||||
{ XK_Up, Window::Key::kUp },
|
||||
{ XK_Down, Window::Key::kDown },
|
||||
{ XK_Left, Window::Key::kLeft },
|
||||
{ XK_Right, Window::Key::kRight }
|
||||
};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
|
||||
if (gPair[i].fXK == keysym) {
|
||||
return gPair[i].fKey;
|
||||
}
|
||||
}
|
||||
return Window::Key::kNONE;
|
||||
}
|
||||
|
||||
static uint32_t get_modifiers(const XEvent& event) {
|
||||
static const struct {
|
||||
unsigned fXMask;
|
||||
unsigned fSkMask;
|
||||
} gModifiers[] = {
|
||||
{ ShiftMask, Window::kShift_ModifierKey },
|
||||
{ ControlMask, Window::kControl_ModifierKey },
|
||||
{ Mod1Mask, Window::kOption_ModifierKey },
|
||||
};
|
||||
|
||||
auto modifiers = 0;
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) {
|
||||
if (event.xkey.state & gModifiers[i].fXMask) {
|
||||
modifiers |= gModifiers[i].fSkMask;
|
||||
}
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
bool Window_unix::handleEvent(const XEvent& event) {
|
||||
switch (event.type) {
|
||||
case ClientMessage:
|
||||
if ((Atom)event.xclient.data.l[0] == fWmDeleteMessage &&
|
||||
gWindowMap.count() == 1) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if (event.xbutton.button == Button1) {
|
||||
this->onMouse(event.xbutton.x, event.xbutton.y,
|
||||
Window::kDown_InputState, get_modifiers(event));
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if (event.xbutton.button == Button1) {
|
||||
this->onMouse(event.xbutton.x, event.xbutton.y,
|
||||
Window::kUp_InputState, get_modifiers(event));
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
// only track if left button is down
|
||||
if (event.xmotion.state & Button1Mask) {
|
||||
this->onMouse(event.xmotion.x, event.xmotion.y,
|
||||
Window::kMove_InputState, get_modifiers(event));
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyPress: {
|
||||
int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0;
|
||||
KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode,
|
||||
0, shiftLevel);
|
||||
if (keysym == XK_Escape) {
|
||||
return true;
|
||||
}
|
||||
Window::Key key = get_key(keysym);
|
||||
if (key != Window::Key::kNONE) {
|
||||
(void) this->onKey(key, Window::kDown_InputState,
|
||||
get_modifiers(event));
|
||||
} else {
|
||||
long uni = keysym2ucs(keysym);
|
||||
if (uni != -1) {
|
||||
(void) this->onChar((SkUnichar) uni,
|
||||
get_modifiers(event));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case KeyRelease: {
|
||||
int shiftLevel = (event.xkey.state & ShiftMask) ? 1 : 0;
|
||||
KeySym keysym = XkbKeycodeToKeysym(fDisplay, event.xkey.keycode,
|
||||
0, shiftLevel);
|
||||
Window::Key key = get_key(keysym);
|
||||
(void) this->onKey(key, Window::kUp_InputState,
|
||||
get_modifiers(event));
|
||||
} break;
|
||||
|
||||
|
||||
default:
|
||||
// these events should be handled in the main event loop
|
||||
SkASSERT(event.type != Expose && event.type != ConfigureNotify);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window_unix::setTitle(const char* title) {
|
||||
XTextProperty textproperty;
|
||||
XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty);
|
||||
XSetWMName(fDisplay, fHWnd, &textproperty);
|
||||
}
|
||||
|
||||
void Window_unix::show() {
|
||||
XMapWindow(fDisplay, fHWnd);
|
||||
}
|
||||
|
||||
bool Window_unix::attach(BackendType attachType, const DisplayParams& params) {
|
||||
ContextPlatformData_unix platformData;
|
||||
platformData.fDisplay = fDisplay;
|
||||
platformData.fHWnd = fHWnd;
|
||||
XWindowAttributes attribs;
|
||||
XGetWindowAttributes(fDisplay, fHWnd, &attribs);
|
||||
platformData.fVisualID = XVisualIDFromVisual(attribs.visual);
|
||||
switch (attachType) {
|
||||
case kVulkan_BackendType:
|
||||
default:
|
||||
fWindowContext = VulkanWindowContext::Create((void*)&platformData, params);
|
||||
break;
|
||||
}
|
||||
|
||||
return (SkToBool(fWindowContext));
|
||||
}
|
||||
|
||||
void Window_unix::onInval() {
|
||||
XEvent event;
|
||||
event.type = Expose;
|
||||
event.xexpose.send_event = True;
|
||||
event.xexpose.display = fDisplay;
|
||||
event.xexpose.window = fHWnd;
|
||||
event.xexpose.x = 0;
|
||||
event.xexpose.y = 0;
|
||||
event.xexpose.width = fWidth;
|
||||
event.xexpose.height = fHeight;
|
||||
event.xexpose.count = 0;
|
||||
|
||||
XSendEvent(fDisplay, fHWnd, False, 0, &event);
|
||||
}
|
||||
|
||||
} // namespace sk_app
|
86
tools/viewer/sk_app/unix/Window_unix.h
Normal file
86
tools/viewer/sk_app/unix/Window_unix.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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_unix_DEFINED
|
||||
#define Window_unix_DEFINED
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include "../Window.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkTDynamicHash.h"
|
||||
|
||||
typedef Window XWindow;
|
||||
|
||||
namespace sk_app {
|
||||
|
||||
struct ContextPlatformData_unix {
|
||||
Display* fDisplay;
|
||||
XWindow fHWnd;
|
||||
VisualID fVisualID;
|
||||
};
|
||||
|
||||
class Window_unix : public Window {
|
||||
public:
|
||||
Window_unix() : Window() {}
|
||||
~Window_unix() override {}
|
||||
|
||||
bool init(Display* display);
|
||||
|
||||
void setTitle(const char*) override;
|
||||
void show() override;
|
||||
|
||||
bool attach(BackendType attachType, const DisplayParams& params) override;
|
||||
|
||||
void onInval() override;
|
||||
|
||||
bool handleEvent(const XEvent& event);
|
||||
|
||||
static const XWindow& GetKey(const Window_unix& w) {
|
||||
return w.fHWnd;
|
||||
}
|
||||
|
||||
static uint32_t Hash(const XWindow& w) {
|
||||
return SkChecksum::Mix(w);
|
||||
}
|
||||
|
||||
static SkTDynamicHash<Window_unix, XWindow> gWindowMap;
|
||||
|
||||
void markPendingPaint() { fPendingPaint = true; }
|
||||
void finishPaint() {
|
||||
if (fPendingPaint) {
|
||||
this->onPaint();
|
||||
fPendingPaint = false;
|
||||
}
|
||||
}
|
||||
|
||||
void markPendingResize(int width, int height) {
|
||||
fPendingWidth = width;
|
||||
fPendingHeight = height;
|
||||
fPendingResize = true;
|
||||
}
|
||||
void finishResize() {
|
||||
if (fPendingResize) {
|
||||
this->onResize(fPendingWidth, fPendingHeight);
|
||||
fPendingResize = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Display* fDisplay;
|
||||
XWindow fHWnd;
|
||||
|
||||
Atom fWmDeleteMessage;
|
||||
|
||||
bool fPendingPaint;
|
||||
int fPendingWidth;
|
||||
int fPendingHeight;
|
||||
bool fPendingResize;
|
||||
};
|
||||
|
||||
} // namespace sk_app
|
||||
|
||||
#endif
|
90
tools/viewer/sk_app/unix/main_unix.cpp
Normal file
90
tools/viewer/sk_app/unix/main_unix.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 "SkTypes.h"
|
||||
#include "SkTHash.h"
|
||||
#include "Timer.h"
|
||||
#include "Window_unix.h"
|
||||
#include "../Application.h"
|
||||
|
||||
using sk_app::Application;
|
||||
|
||||
static double now_ms() { return SkTime::GetNSecs() * 1e-6; }
|
||||
|
||||
void finishWindow(sk_app::Window_unix* win) {
|
||||
win->finishResize();
|
||||
win->finishPaint();
|
||||
}
|
||||
|
||||
int main(int argc, char**argv) {
|
||||
|
||||
Display* display = XOpenDisplay(nullptr);
|
||||
|
||||
Application* app = Application::Create(argc, argv, (void*)display);
|
||||
|
||||
double currentTime = 0.0;
|
||||
double previousTime = 0.0;
|
||||
|
||||
// Get the file descriptor for the X display
|
||||
int x11_fd = ConnectionNumber(display);
|
||||
fd_set in_fds;
|
||||
|
||||
SkTHashSet<sk_app::Window_unix*> pendingWindows;
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
// Create a file description set containing x11_fd
|
||||
FD_ZERO(&in_fds);
|
||||
FD_SET(x11_fd, &in_fds);
|
||||
|
||||
// Set a sleep timer
|
||||
struct timeval tv;
|
||||
tv.tv_usec = 100;
|
||||
tv.tv_sec = 0;
|
||||
|
||||
// Wait for an event on the file descriptor or for timer expiration
|
||||
(void) select(1, &in_fds, NULL, NULL, &tv);
|
||||
|
||||
// Handle XEvents (if any) and flush the input
|
||||
XEvent event;
|
||||
while (XPending(display) && !done) {
|
||||
XNextEvent(display, &event);
|
||||
|
||||
sk_app::Window_unix* win = sk_app::Window_unix::gWindowMap.find(event.xany.window);
|
||||
// paint and resize events get collapsed
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
win->markPendingPaint();
|
||||
pendingWindows.add(win);
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
win->markPendingResize(event.xconfigurerequest.width,
|
||||
event.xconfigurerequest.height);
|
||||
pendingWindows.add(win);
|
||||
break;
|
||||
default:
|
||||
if (win->handleEvent(event)) {
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pendingWindows.foreach(finishWindow);
|
||||
if (pendingWindows.count() > 0) {
|
||||
previousTime = currentTime;
|
||||
currentTime = now_ms();
|
||||
app->onIdle(currentTime - previousTime);
|
||||
}
|
||||
pendingWindows.reset();
|
||||
}
|
||||
|
||||
delete app;
|
||||
|
||||
XCloseDisplay(display);
|
||||
|
||||
return 0;
|
||||
}
|
@ -47,7 +47,7 @@ VkSurfaceKHR VulkanWindowContext::createVkSurface(VkInstance instance, void* pla
|
||||
|
||||
// Platform dependant call
|
||||
bool VulkanWindowContext::canPresent(VkInstance instance, VkPhysicalDevice physDev,
|
||||
uint32_t queueFamilyIndex) {
|
||||
uint32_t queueFamilyIndex, void*) {
|
||||
static PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
|
||||
getPhysicalDeviceWin32PresentationSupportKHR = nullptr;
|
||||
if (!getPhysicalDeviceWin32PresentationSupportKHR) {
|
||||
|
Loading…
Reference in New Issue
Block a user