diff options
author | Brian Osman <brianosman@google.com> | 2017-11-21 13:18:02 -0500 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-11-21 18:37:19 +0000 |
commit | eff04b5ec287e0fee0d44207c10d2d11f7eade8a (patch) | |
tree | ea2cf00ea329c81611536aaa9a9f1eca47c67e9a /tools/sk_app/mac | |
parent | 2aa09dbe8aced37aa6bb285e62df45deb0e81650 (diff) |
Remove SampleApp and convert HelloWorld to sk_app
There is still a large amount of views code that could be trimmed down,
but which is used to implement samples (in viewer). Seemed simpler to
remove some of this code in pieces.
Bug: skia:
Change-Id: Ia3415060d03c8de604a154e3dc38379b754daab6
Reviewed-on: https://skia-review.googlesource.com/72801
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'tools/sk_app/mac')
-rw-r--r-- | tools/sk_app/mac/GLWindowContext_mac.cpp | 109 | ||||
-rw-r--r-- | tools/sk_app/mac/RasterWindowContext_mac.cpp | 136 | ||||
-rw-r--r-- | tools/sk_app/mac/WindowContextFactory_mac.h | 38 | ||||
-rw-r--r-- | tools/sk_app/mac/Window_mac.cpp | 277 | ||||
-rw-r--r-- | tools/sk_app/mac/Window_mac.h | 64 | ||||
-rw-r--r-- | tools/sk_app/mac/main_mac.cpp | 58 |
6 files changed, 682 insertions, 0 deletions
diff --git a/tools/sk_app/mac/GLWindowContext_mac.cpp b/tools/sk_app/mac/GLWindowContext_mac.cpp new file mode 100644 index 0000000000..7f09d54522 --- /dev/null +++ b/tools/sk_app/mac/GLWindowContext_mac.cpp @@ -0,0 +1,109 @@ + +/* + * 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 <OpenGL/gl.h> +#include "../GLWindowContext.h" +#include "SDL.h" +#include "WindowContextFactory_mac.h" +#include "gl/GrGLInterface.h" + +using sk_app::DisplayParams; +using sk_app::window_context_factory::MacWindowInfo; +using sk_app::GLWindowContext; + +namespace { + +class GLWindowContext_mac : public GLWindowContext { +public: + GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&); + + ~GLWindowContext_mac() override; + + void onSwapBuffers() override; + + sk_sp<const GrGLInterface> onInitializeContext() override; + void onDestroyContext() override; + +private: + SDL_Window* fWindow; + SDL_GLContext fGLContext; + + typedef GLWindowContext INHERITED; +}; + +GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params) + : INHERITED(params) + , fWindow(info.fWindow) + , fGLContext(nullptr) { + + // any config code here (particularly for msaa)? + + this->initializeContext(); +} + +GLWindowContext_mac::~GLWindowContext_mac() { + this->destroyContext(); +} + +sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() { + SkASSERT(fWindow); + + fGLContext = SDL_GL_CreateContext(fWindow); + if (!fGLContext) { + SkDebugf("%s\n", SDL_GetError()); + return nullptr; + } + + if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) { + glClearStencil(0); + glClearColor(0, 0, 0, 0); + glStencilMask(0xffffffff); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits); + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount); + + SDL_GetWindowSize(fWindow, &fWidth, &fHeight); + glViewport(0, 0, fWidth, fHeight); + } else { + SkDebugf("MakeCurrent failed: %s\n", SDL_GetError()); + } + return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface()); +} + +void GLWindowContext_mac::onDestroyContext() { + if (!fWindow || !fGLContext) { + return; + } + SDL_GL_DeleteContext(fGLContext); + fGLContext = nullptr; +} + + +void GLWindowContext_mac::onSwapBuffers() { + if (fWindow && fGLContext) { + SDL_GL_SwapWindow(fWindow); + } +} + +} // anonymous namespace + +namespace sk_app { +namespace window_context_factory { + +WindowContext* NewGLForMac(const MacWindowInfo& info, const DisplayParams& params) { + WindowContext* ctx = new GLWindowContext_mac(info, params); + if (!ctx->isValid()) { + delete ctx; + return nullptr; + } + return ctx; +} + +} // namespace window_context_factory +} // namespace sk_app diff --git a/tools/sk_app/mac/RasterWindowContext_mac.cpp b/tools/sk_app/mac/RasterWindowContext_mac.cpp new file mode 100644 index 0000000000..409c49f218 --- /dev/null +++ b/tools/sk_app/mac/RasterWindowContext_mac.cpp @@ -0,0 +1,136 @@ + +/* + * 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 <OpenGL/gl.h> +#include "../GLWindowContext.h" +#include "SDL.h" +#include "SkCanvas.h" +#include "SkColorFilter.h" +#include "WindowContextFactory_mac.h" +#include "gl/GrGLInterface.h" +#include "sk_tool_utils.h" + +using sk_app::DisplayParams; +using sk_app::window_context_factory::MacWindowInfo; +using sk_app::GLWindowContext; + +namespace { + +// We use SDL to support Mac windowing mainly for convenience's sake. However, it +// does not allow us to support a purely raster backend because we have no hooks into +// the NSWindow's drawRect: method. Hence we use GL to handle the update. Should we +// want to avoid this, we will probably need to write our own windowing backend. + +class RasterWindowContext_mac : public GLWindowContext { +public: + RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&); + + ~RasterWindowContext_mac() override; + + sk_sp<SkSurface> getBackbufferSurface() override; + + void onSwapBuffers() override; + + sk_sp<const GrGLInterface> onInitializeContext() override; + void onDestroyContext() override; + +private: + SDL_Window* fWindow; + SDL_GLContext fGLContext; + sk_sp<SkSurface> fBackbufferSurface; + + typedef GLWindowContext INHERITED; +}; + +RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info, + const DisplayParams& params) + : INHERITED(params) + , fWindow(info.fWindow) + , fGLContext(nullptr) { + + // any config code here (particularly for msaa)? + + this->initializeContext(); +} + +RasterWindowContext_mac::~RasterWindowContext_mac() { + this->destroyContext(); +} + +sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() { + SkASSERT(fWindow); + + fGLContext = SDL_GL_CreateContext(fWindow); + if (!fGLContext) { + SkDebugf("%s\n", SDL_GetError()); + return nullptr; + } + + if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) { + glClearStencil(0); + glClearColor(0, 0, 0, 0); + glStencilMask(0xffffffff); + glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits); + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount); + + SDL_GetWindowSize(fWindow, &fWidth, &fHeight); + glViewport(0, 0, fWidth, fHeight); + } else { + SkDebugf("MakeCurrent failed: %s\n", SDL_GetError()); + } + + // make the offscreen image + SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType, + kPremul_SkAlphaType, fDisplayParams.fColorSpace); + fBackbufferSurface = SkSurface::MakeRaster(info); + return sk_sp<const GrGLInterface>(GrGLCreateNativeInterface()); +} + +void RasterWindowContext_mac::onDestroyContext() { + if (!fWindow || !fGLContext) { + return; + } + fBackbufferSurface.reset(nullptr); + SDL_GL_DeleteContext(fGLContext); + fGLContext = nullptr; +} + +sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; } + +void RasterWindowContext_mac::onSwapBuffers() { + if (fWindow && fGLContext) { + // We made/have an off-screen surface. Get the contents as an SkImage: + sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot(); + + sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface(); + SkCanvas* gpuCanvas = gpuSurface->getCanvas(); + gpuCanvas->drawImage(snapshot, 0, 0); + gpuCanvas->flush(); + + SDL_GL_SwapWindow(fWindow); + } +} + +} // anonymous namespace + +namespace sk_app { +namespace window_context_factory { + +WindowContext* NewRasterForMac(const MacWindowInfo& info, const DisplayParams& params) { + WindowContext* ctx = new RasterWindowContext_mac(info, params); + if (!ctx->isValid()) { + delete ctx; + return nullptr; + } + return ctx; +} + +} // namespace window_context_factory +} // namespace sk_app diff --git a/tools/sk_app/mac/WindowContextFactory_mac.h b/tools/sk_app/mac/WindowContextFactory_mac.h new file mode 100644 index 0000000000..3adc68bbc2 --- /dev/null +++ b/tools/sk_app/mac/WindowContextFactory_mac.h @@ -0,0 +1,38 @@ + +/* + * 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 WindowContextFactory_mac_DEFINED +#define WindowContextFactory_mac_DEFINED + +#include "SDL.h" + +namespace sk_app { + +class WindowContext; +struct DisplayParams; + +namespace window_context_factory { + +struct MacWindowInfo { + SDL_Window* fWindow; +}; + +inline WindowContext* NewVulkanForMac(const MacWindowInfo&, const DisplayParams&) { + // No Vulkan support on Mac. + return nullptr; +} + +WindowContext* NewGLForMac(const MacWindowInfo&, const DisplayParams&); + +WindowContext* NewRasterForMac(const MacWindowInfo&, const DisplayParams&); + +} // namespace window_context_factory + +} // namespace sk_app + +#endif diff --git a/tools/sk_app/mac/Window_mac.cpp b/tools/sk_app/mac/Window_mac.cpp new file mode 100644 index 0000000000..8de5b10450 --- /dev/null +++ b/tools/sk_app/mac/Window_mac.cpp @@ -0,0 +1,277 @@ +/* +* 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 "SkUtils.h" +#include "Timer.h" +#include "WindowContextFactory_mac.h" +#include "Window_mac.h" + +namespace sk_app { + +SkTDynamicHash<Window_mac, Uint32> Window_mac::gWindowMap; + +Window* Window::CreateNativeWindow(void*) { + Window_mac* window = new Window_mac(); + if (!window->initWindow()) { + delete window; + return nullptr; + } + + return window; +} + +bool Window_mac::initWindow() { + if (fRequestedDisplayParams.fMSAASampleCount != fMSAASampleCount) { + this->closeWindow(); + } + // we already have a window + if (fWindow) { + return true; + } + + constexpr int initialWidth = 1280; + constexpr int initialHeight = 960; + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + + if (fRequestedDisplayParams.fMSAASampleCount > 0) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, fRequestedDisplayParams.fMSAASampleCount); + } else { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + } + // TODO: handle other display params + + uint32_t windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + fWindow = SDL_CreateWindow("SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + initialWidth, initialHeight, windowFlags); + + if (!fWindow) { + return false; + } + + fMSAASampleCount = fRequestedDisplayParams.fMSAASampleCount; + + // add to hashtable of windows + fWindowID = SDL_GetWindowID(fWindow); + gWindowMap.add(this); + + return true; +} + +void Window_mac::closeWindow() { + if (fWindow) { + gWindowMap.remove(fWindowID); + SDL_DestroyWindow(fWindow); + fWindowID = 0; + fWindow = nullptr; + } +} + +static Window::Key get_key(const SDL_Keysym& keysym) { + static const struct { + SDL_Keycode fSDLK; + Window::Key fKey; + } gPair[] = { + { SDLK_BACKSPACE, Window::Key::kBack }, + { SDLK_CLEAR, Window::Key::kBack }, + { SDLK_RETURN, Window::Key::kOK }, + { SDLK_UP, Window::Key::kUp }, + { SDLK_DOWN, Window::Key::kDown }, + { SDLK_LEFT, Window::Key::kLeft }, + { SDLK_RIGHT, Window::Key::kRight }, + { SDLK_TAB, Window::Key::kTab }, + { SDLK_PAGEUP, Window::Key::kPageUp }, + { SDLK_PAGEDOWN, Window::Key::kPageDown }, + { SDLK_HOME, Window::Key::kHome }, + { SDLK_END, Window::Key::kEnd }, + { SDLK_DELETE, Window::Key::kDelete }, + { SDLK_ESCAPE, Window::Key::kEscape }, + { SDLK_LSHIFT, Window::Key::kShift }, + { SDLK_RSHIFT, Window::Key::kShift }, + { SDLK_LCTRL, Window::Key::kCtrl }, + { SDLK_RCTRL, Window::Key::kCtrl }, + { SDLK_LALT, Window::Key::kOption }, + { SDLK_LALT, Window::Key::kOption }, + { 'A', Window::Key::kA }, + { 'C', Window::Key::kC }, + { 'V', Window::Key::kV }, + { 'X', Window::Key::kX }, + { 'Y', Window::Key::kY }, + { 'Z', Window::Key::kZ }, + }; + for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) { + if (gPair[i].fSDLK == keysym.sym) { + return gPair[i].fKey; + } + } + return Window::Key::kNONE; +} + +static uint32_t get_modifiers(const SDL_Event& event) { + static const struct { + unsigned fSDLMask; + unsigned fSkMask; + } gModifiers[] = { + { KMOD_SHIFT, Window::kShift_ModifierKey }, + { KMOD_CTRL, Window::kControl_ModifierKey }, + { KMOD_ALT, Window::kOption_ModifierKey }, + }; + + auto modifiers = 0; + + switch (event.type) { + case SDL_KEYDOWN: + // fall through + case SDL_KEYUP: { + for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { + if (event.key.keysym.mod & gModifiers[i].fSDLMask) { + modifiers |= gModifiers[i].fSkMask; + } + } + if (0 == event.key.repeat) { + modifiers |= Window::kFirstPress_ModifierKey; + } + break; + } + + default: { + SDL_Keymod mod = SDL_GetModState(); + for (size_t i = 0; i < SK_ARRAY_COUNT(gModifiers); ++i) { + if (mod & gModifiers[i].fSDLMask) { + modifiers |= gModifiers[i].fSkMask; + } + } + break; + } + } + return modifiers; +} + +bool Window_mac::HandleWindowEvent(const SDL_Event& event) { + Window_mac* win = gWindowMap.find(event.window.windowID); + if (win && win->handleEvent(event)) { + return true; + } + + return false; +} + +bool Window_mac::handleEvent(const SDL_Event& event) { + switch (event.type) { + case SDL_WINDOWEVENT: + if (SDL_WINDOWEVENT_EXPOSED == event.window.event) { + this->onPaint(); + } else if (SDL_WINDOWEVENT_RESIZED == event.window.event) { + this->onResize(event.window.data1, event.window.data2); + } + break; + + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) { + this->onMouse(event.button.x, event.button.y, + Window::kDown_InputState, get_modifiers(event)); + } + break; + + case SDL_MOUSEBUTTONUP: + if (event.button.button == SDL_BUTTON_LEFT) { + this->onMouse(event.button.x, event.button.y, + Window::kUp_InputState, get_modifiers(event)); + } + break; + + case SDL_MOUSEMOTION: + this->onMouse(event.motion.x, event.motion.y, + Window::kMove_InputState, get_modifiers(event)); + break; + + case SDL_MOUSEWHEEL: + this->onMouseWheel(event.wheel.y, get_modifiers(event)); + break; + + case SDL_KEYDOWN: { + Window::Key key = get_key(event.key.keysym); + if (key != Window::Key::kNONE) { + if (!this->onKey(key, Window::kDown_InputState, get_modifiers(event))) { + if (event.key.keysym.sym == SDLK_ESCAPE) { + return true; + } + } + } + } break; + + case SDL_KEYUP: { + Window::Key key = get_key(event.key.keysym); + if (key != Window::Key::kNONE) { + (void) this->onKey(key, Window::kUp_InputState, + get_modifiers(event)); + } + } break; + + case SDL_TEXTINPUT: { + const char* textIter = &event.text.text[0]; + while (SkUnichar c = SkUTF8_NextUnichar(&textIter)) { + (void) this->onChar(c, get_modifiers(event)); + } + } break; + + default: + break; + } + + return false; +} + +void Window_mac::setTitle(const char* title) { + SDL_SetWindowTitle(fWindow, title); +} + +void Window_mac::show() { + SDL_ShowWindow(fWindow); +} + +bool Window_mac::attach(BackendType attachType) { + this->initWindow(); + + window_context_factory::MacWindowInfo info; + info.fWindow = fWindow; + switch (attachType) { + case kRaster_BackendType: + fWindowContext = NewRasterForMac(info, fRequestedDisplayParams); + break; + + case kNativeGL_BackendType: + default: + fWindowContext = NewGLForMac(info, fRequestedDisplayParams); + break; + } + this->onBackendCreated(); + + return (SkToBool(fWindowContext)); +} + +void Window_mac::onInval() { + SDL_Event sdlevent; + sdlevent.type = SDL_WINDOWEVENT; + sdlevent.window.windowID = fWindowID; + sdlevent.window.event = SDL_WINDOWEVENT_EXPOSED; + SDL_PushEvent(&sdlevent); +} + +} // namespace sk_app diff --git a/tools/sk_app/mac/Window_mac.h b/tools/sk_app/mac/Window_mac.h new file mode 100644 index 0000000000..aa5c8df696 --- /dev/null +++ b/tools/sk_app/mac/Window_mac.h @@ -0,0 +1,64 @@ +/* +* 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" + +#include "SDL.h" + +namespace sk_app { + +class Window_mac : public Window { +public: + Window_mac() + : INHERITED() + , fWindow(nullptr) + , fWindowID(0) + , fMSAASampleCount(0) {} + ~Window_mac() override { this->closeWindow(); } + + bool initWindow(); + + void setTitle(const char*) override; + void show() override; + + bool attach(BackendType) override; + + void onInval() override; + + static bool HandleWindowEvent(const SDL_Event& event); + + static const Uint32& GetKey(const Window_mac& w) { + return w.fWindowID; + } + + static uint32_t Hash(const Uint32& winID) { + return winID; + } + +private: + bool handleEvent(const SDL_Event& event); + + void closeWindow(); + + static SkTDynamicHash<Window_mac, Uint32> gWindowMap; + + SDL_Window* fWindow; + Uint32 fWindowID; + + int fMSAASampleCount; + + typedef Window INHERITED; +}; + +} // namespace sk_app + +#endif diff --git a/tools/sk_app/mac/main_mac.cpp b/tools/sk_app/mac/main_mac.cpp new file mode 100644 index 0000000000..6dcf5b93f7 --- /dev/null +++ b/tools/sk_app/mac/main_mac.cpp @@ -0,0 +1,58 @@ +/* +* 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 "SDL.h" +#include "Timer.h" +#include "Window_mac.h" +#include "../Application.h" + +using sk_app::Application; + +int main(int argc, char* argv[]) { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { + SkDebugf("Could not initialize SDL!\n"); + return 1; + } + + Application* app = Application::Create(argc, argv, nullptr); + + SDL_Event event; + bool done = false; + while (!done) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + // events handled by the windows + case SDL_WINDOWEVENT: + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + case SDL_KEYDOWN: + case SDL_KEYUP: + case SDL_TEXTINPUT: + done = sk_app::Window_mac::HandleWindowEvent(event); + break; + + case SDL_QUIT: + done = true; + break; + + default: + break; + } + } + + app->onIdle(); + } + delete app; + + SDL_Quit(); + + return 0; +} |