diff options
-rw-r--r-- | gyp/most.gyp | 2 | ||||
-rw-r--r-- | gyp/viewer.gyp | 4 | ||||
-rw-r--r-- | tools/viewer/sk_app/mac/GLWindowContext_mac.cpp | 111 | ||||
-rw-r--r-- | tools/viewer/sk_app/mac/GLWindowContext_mac.h | 42 | ||||
-rw-r--r-- | tools/viewer/sk_app/mac/Window_mac.cpp | 308 | ||||
-rw-r--r-- | tools/viewer/sk_app/mac/Window_mac.h | 67 | ||||
-rw-r--r-- | tools/viewer/sk_app/mac/main_mac.cpp | 75 |
7 files changed, 608 insertions, 1 deletions
diff --git a/gyp/most.gyp b/gyp/most.gyp index 37c802b841..5b5392618e 100644 --- a/gyp/most.gyp +++ b/gyp/most.gyp @@ -67,7 +67,7 @@ 'skiaserve.gyp:skiaserve', ], }], - [ 'skia_os in ["win", "linux", "android"]', { + [ 'skia_os in ["win", "linux", "android", "mac"]', { 'dependencies': [ 'viewer.gyp:viewer', ], diff --git a/gyp/viewer.gyp b/gyp/viewer.gyp index 5bec25c756..b2563ef537 100644 --- a/gyp/viewer.gyp +++ b/gyp/viewer.gyp @@ -101,6 +101,10 @@ 'sources/': [ ['exclude', '_win.(h|cpp)$'], ], }], + ['skia_os != "mac"', { + 'sources/': [ ['exclude', '_mac.(h|cpp)$'], + ], + }], ['skia_vulkan == 0', { 'sources/': [ ['exclude', 'Vulkan'] ], diff --git a/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp b/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp new file mode 100644 index 0000000000..aa700e3165 --- /dev/null +++ b/tools/viewer/sk_app/mac/GLWindowContext_mac.cpp @@ -0,0 +1,111 @@ + +/* + * 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 "GLWindowContext_mac.h" + +//#include <GL/gl.h> + +#include "Window_mac.h" + +namespace sk_app { + +// platform-dependent create +GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams& params) { + GLWindowContext_mac* ctx = new GLWindowContext_mac(platformData, params); + if (!ctx->isValid()) { + delete ctx; + return nullptr; + } + return ctx; +} + +GLWindowContext_mac::GLWindowContext_mac(void* platformData, const DisplayParams& params) + : GLWindowContext(platformData, params) +#if 0 + // TODO: init Mac-specific OpenGL objects + , fDisplay(nullptr) + , fWindow(0) + , fGLContext(0) +#endif + { + + // any config code here (particularly for msaa)? + + this->initializeContext(platformData, params); +} + +GLWindowContext_mac::~GLWindowContext_mac() { + this->destroyContext(); +} + +void GLWindowContext_mac::onInitializeContext(void* platformData, const DisplayParams& params) { +#if 0 + // TODO: Init for Mac + ContextPlatformData_mac* unixPlatformData = + reinterpret_cast<ContextPlatformData_mac*>(platformData); + + if (unixPlatformData) { + fDisplay = unixPlatformData->fDisplay; + fWindow = unixPlatformData->fWindow; + fVisualInfo = unixPlatformData->fVisualInfo; + } + SkASSERT(fDisplay); + + fGLContext = glXCreateContext(fDisplay, fVisualInfo, nullptr, GL_TRUE); + if (!fGLContext) { + return; + } + + if (glXMakeCurrent(fDisplay, fWindow, fGLContext)) { + glClearStencil(0); + glClearColor(0, 0, 0, 0); + glStencilMask(0xffffffff); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + int redBits, greenBits, blueBits; + glXGetConfig(fDisplay, fVisualInfo, GLX_RED_SIZE, &redBits); + glXGetConfig(fDisplay, fVisualInfo, GLX_GREEN_SIZE, &greenBits); + glXGetConfig(fDisplay, fVisualInfo, GLX_BLUE_SIZE, &blueBits); + fColorBits = redBits + greenBits + blueBits; + glXGetConfig(fDisplay, fVisualInfo, GLX_STENCIL_SIZE, &fStencilBits); + glXGetConfig(fDisplay, fVisualInfo, GLX_SAMPLES_ARB, &fSampleCount); + + XWindow root; + int x, y; + unsigned int border_width, depth; + XGetGeometry(fDisplay, fWindow, &root, &x, &y, + (unsigned int*)&fWidth, (unsigned int*)&fHeight, &border_width, &depth); + glViewport(0, 0, fWidth, fHeight); + } +#endif +} + +void GLWindowContext_mac::onDestroyContext() { +#if 0 + // TODO: teardown for Mac + if (!fDisplay || !fGLContext) { + return; + } + glXMakeCurrent(fDisplay, None, nullptr); + glXDestroyContext(fDisplay, fGLContext); + fGLContext = nullptr; +#endif +} + + +void GLWindowContext_mac::onSwapBuffers() { +#if 0 + // TODO: swap for Mac + if (fDisplay && fGLContext) { + glXSwapBuffers(fDisplay, fWindow); + } +#endif +} + + +} //namespace sk_app diff --git a/tools/viewer/sk_app/mac/GLWindowContext_mac.h b/tools/viewer/sk_app/mac/GLWindowContext_mac.h new file mode 100644 index 0000000000..e889c4cd31 --- /dev/null +++ b/tools/viewer/sk_app/mac/GLWindowContext_mac.h @@ -0,0 +1,42 @@ + +/* + * 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 GLWindowContext_mac_DEFINED +#define GLWindowContext_mac_DEFINED + +#include "../GLWindowContext.h" +#include "Window_mac.h" + +namespace sk_app { + +class GLWindowContext_mac : public GLWindowContext { +public: + friend GLWindowContext* GLWindowContext::Create(void* platformData, const DisplayParams&); + + ~GLWindowContext_mac() override; + + void onSwapBuffers() override; + + void onInitializeContext(void*, const DisplayParams&) override; + void onDestroyContext() override; + +private: + GLWindowContext_mac(void*, const DisplayParams&); + +#if 0 + // TODO: add Mac-specific GL display objects + Display* fDisplay; + XWindow fWindow; + XVisualInfo* fVisualInfo; + GLXContext fGLContext; +#endif +}; + + +} + +#endif diff --git a/tools/viewer/sk_app/mac/Window_mac.cpp b/tools/viewer/sk_app/mac/Window_mac.cpp new file mode 100644 index 0000000000..fdc6f80bd6 --- /dev/null +++ b/tools/viewer/sk_app/mac/Window_mac.cpp @@ -0,0 +1,308 @@ +/* +* 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 "../GLWindowContext.h" +#include "Window_mac.h" + +namespace sk_app { + +Window* Window::CreateNativeWindow(void* platformData) { +#if 0 + // TODO: platform-specific window creation + Display* display = (Display*)platformData; + + Window_mac* window = new Window_mac(); + if (!window->initWindow(display, nullptr)) { + delete window; + return nullptr; + } + + return window; +#else + return nullptr; +#endif +} + +#if 0 + // TODO: Implement Mac window code + +const long kEventMask = ExposureMask | StructureNotifyMask | + KeyPressMask | KeyReleaseMask | + PointerMotionMask | ButtonPressMask | ButtonReleaseMask; + +bool Window_mac::initWindow(Display* display, const DisplayParams* params) { + if (params && params->fMSAASampleCount != fMSAASampleCount) { + this->closeWindow(); + } + // we already have a window + if (fDisplay) { + return true; + } + fDisplay = display; + + fWidth = 1280; + fHeight = 960; + + // Attempt to create a window that supports GL + GLint att[] = { + GLX_RGBA, + GLX_DEPTH_SIZE, 24, + GLX_DOUBLEBUFFER, + GLX_STENCIL_SIZE, 8, + None + }; + SkASSERT(nullptr == fVisualInfo); + if (params && params->fMSAASampleCount > 0) { + static const GLint kAttCount = SK_ARRAY_COUNT(att); + GLint msaaAtt[kAttCount + 4]; + memcpy(msaaAtt, att, sizeof(att)); + SkASSERT(None == msaaAtt[kAttCount - 1]); + msaaAtt[kAttCount - 1] = GLX_SAMPLE_BUFFERS_ARB; + msaaAtt[kAttCount + 0] = 1; + msaaAtt[kAttCount + 1] = GLX_SAMPLES_ARB; + msaaAtt[kAttCount + 2] = params->fMSAASampleCount; + msaaAtt[kAttCount + 3] = None; + fVisualInfo = glXChooseVisual(display, DefaultScreen(display), msaaAtt); + fMSAASampleCount = params->fMSAASampleCount; + } + if (nullptr == fVisualInfo) { + fVisualInfo = glXChooseVisual(display, DefaultScreen(display), att); + fMSAASampleCount = 0; + } + + if (fVisualInfo) { + Colormap colorMap = XCreateColormap(display, + RootWindow(display, fVisualInfo->screen), + fVisualInfo->visual, + AllocNone); + XSetWindowAttributes swa; + swa.colormap = colorMap; + swa.event_mask = kEventMask; + fWindow = XCreateWindow(display, + RootWindow(display, fVisualInfo->screen), + 0, 0, // x, y + fWidth, fHeight, + 0, // border width + fVisualInfo->depth, + InputOutput, + fVisualInfo->visual, + CWEventMask | CWColormap, + &swa); + } else { + // Create a simple window instead. We will not be able to show GL + fWindow = XCreateSimpleWindow(display, + DefaultRootWindow(display), + 0, 0, // x, y + fWidth, fHeight, + 0, // border width + 0, // border value + 0); // background value + XSelectInput(display, fWindow, kEventMask); + } + + if (!fWindow) { + return false; + } + + // set up to catch window delete message + fWmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False); + XSetWMProtocols(display, fWindow, &fWmDeleteMessage, 1); + + // add to hashtable of windows + gWindowMap.add(this); + + // init event variables + fPendingPaint = false; + fPendingResize = false; + + return true; +} + +void Window_mac::closeWindow() { + if (fDisplay) { + this->detach(); + SkASSERT(fGC); + XFreeGC(fDisplay, fGC); + fGC = nullptr; + gWindowMap.remove(fWindow); + XDestroyWindow(fDisplay, fWindow); + fWindow = 0; + fVisualInfo = nullptr; + fDisplay = nullptr; + fMSAASampleCount = 0; + } +} + +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_mac::handleEvent(const XEvent& event) { + switch (event.type) { + case MapNotify: + if (!fGC) { + fGC = XCreateGC(fDisplay, fWindow, 0, nullptr); + } + break; + + 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_mac::setTitle(const char* title) { + XTextProperty textproperty; + XStringListToTextProperty(const_cast<char**>(&title), 1, &textproperty); + XSetWMName(fDisplay, fWindow, &textproperty); +} + +void Window_mac::show() { + XMapWindow(fDisplay, fWindow); +} + +bool Window_mac::attach(BackendType attachType, const DisplayParams& params) { + this->initWindow(fDisplay, ¶ms); + + ContextPlatformData_mac platformData; + platformData.fDisplay = fDisplay; + platformData.fWindow = fWindow; + platformData.fVisualInfo = fVisualInfo; + switch (attachType) { +#ifdef SK_VULKAN + case kVulkan_BackendType: + fWindowContext = VulkanWindowContext::Create((void*)&platformData, params); + break; +#endif + case kNativeGL_BackendType: + default: + fWindowContext = GLWindowContext::Create((void*)&platformData, params); + break; + } + + return (SkToBool(fWindowContext)); +} + +void Window_mac::onInval() { + XEvent event; + event.type = Expose; + event.xexpose.send_event = True; + event.xexpose.display = fDisplay; + event.xexpose.window = fWindow; + event.xexpose.x = 0; + event.xexpose.y = 0; + event.xexpose.width = fWidth; + event.xexpose.height = fHeight; + event.xexpose.count = 0; + + XSendEvent(fDisplay, fWindow, False, 0, &event); +} +#endif + +} // namespace sk_app diff --git a/tools/viewer/sk_app/mac/Window_mac.h b/tools/viewer/sk_app/mac/Window_mac.h new file mode 100644 index 0000000000..016b134465 --- /dev/null +++ b/tools/viewer/sk_app/mac/Window_mac.h @@ -0,0 +1,67 @@ +/* +* Copyright 2016 Google Inc. +* +* Use of this source code is governed by a BSD-style license that can be +* found in the LICENSE file. +*/ + +#ifndef Window_mac_DEFINED +#define Window_mac_DEFINED + +#include "../Window.h" +#include "SkChecksum.h" +#include "SkTDynamicHash.h" + +namespace sk_app { + +struct ContextPlatformData_mac { +#if 0 + // TODO: use Mac-specific objects + Display* fDisplay; + XWindow fWindow; + XVisualInfo* fVisualInfo; +#endif +}; + +class Window_mac : public Window { +public: + Window_mac() : Window() +#if 0 + // TODO: use Mac-specific objects + , fDisplay(nullptr) + , fWindow(0) + , fGC(nullptr) + , fVisualInfo(nullptr) +#endif + , fMSAASampleCount(0) {} + ~Window_mac() override { this->closeWindow(); } + +#if 0 + // TODO: need to init with Mac-specific data + bool initWindow(Display* display, const DisplayParams* params); +#endif + + void setTitle(const char*) override; + void show() override; + + bool attach(BackendType attachType, const DisplayParams& params) override; + + void onInval() override; + +private: + void closeWindow(); + +#if 0 + // TODO: use Mac-specific window data + Display* fDisplay; + XWindow fWindow; + GC fGC; + XVisualInfo* fVisualInfo; +#endif + + int fMSAASampleCount; +}; + +} // namespace sk_app + +#endif diff --git a/tools/viewer/sk_app/mac/main_mac.cpp b/tools/viewer/sk_app/mac/main_mac.cpp new file mode 100644 index 0000000000..94bc99e01e --- /dev/null +++ b/tools/viewer/sk_app/mac/main_mac.cpp @@ -0,0 +1,75 @@ +/* +* 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_mac.h" +#include "../Application.h" + +using sk_app::Application; + +int main(int argc, char**argv) { +#if 0 + // TODO: use Mac main loop + + Display* display = XOpenDisplay(nullptr); + + Application* app = Application::Create(argc, argv, (void*)display); + + // Get the file descriptor for the X display + int x11_fd = ConnectionNumber(display); + fd_set in_fds; + + SkTHashSet<sk_app::Window_mac*> 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_mac* win = sk_app::Window_mac::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; + } + } + } + + delete app; + + XCloseDisplay(display); +#endif + + return 0; +} |