1
2 /*
3 * Copyright 2016 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9 #include "../GLWindowContext.h"
10 #include "SkCanvas.h"
11 #include "SkColorFilter.h"
12 #include "sk_tool_utils.h"
13 #include "WindowContextFactory_mac.h"
14
15 #include "SDL.h"
16
17 #include <OpenGL/gl.h>
18
19 using sk_app::DisplayParams;
20 using sk_app::window_context_factory::MacWindowInfo;
21 using sk_app::GLWindowContext;
22
23 namespace {
24
25 // We use SDL to support Mac windowing mainly for convenience's sake. However, it
26 // does not allow us to support a purely raster backend because we have no hooks into
27 // the NSWindow's drawRect: method. Hence we use GL to handle the update. Should we
28 // want to avoid this, we will probably need to write our own windowing backend.
29
30 class RasterWindowContext_mac : public GLWindowContext {
31 public:
32 RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
33
34 ~RasterWindowContext_mac() override;
35
36 sk_sp<SkSurface> getBackbufferSurface() override;
37
38 void onSwapBuffers() override;
39
40 void onInitializeContext() override;
41 void onDestroyContext() override;
42
43 private:
44 SDL_Window* fWindow;
45 SDL_GLContext fGLContext;
46 sk_sp<SkSurface> fBackbufferSurface;
47
48 typedef GLWindowContext INHERITED;
49 };
50
RasterWindowContext_mac(const MacWindowInfo & info,const DisplayParams & params)51 RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
52 const DisplayParams& params)
53 : INHERITED(params)
54 , fWindow(info.fWindow)
55 , fGLContext(nullptr) {
56
57 // any config code here (particularly for msaa)?
58
59 this->initializeContext();
60 }
61
~RasterWindowContext_mac()62 RasterWindowContext_mac::~RasterWindowContext_mac() {
63 this->destroyContext();
64 }
65
onInitializeContext()66 void RasterWindowContext_mac::onInitializeContext() {
67 SkASSERT(fWindow);
68
69 fGLContext = SDL_GL_CreateContext(fWindow);
70 if (!fGLContext) {
71 SkDebugf("%s\n", SDL_GetError());
72 return;
73 }
74
75 if (0 == SDL_GL_MakeCurrent(fWindow, fGLContext)) {
76 glClearStencil(0);
77 glClearColor(0, 0, 0, 0);
78 glStencilMask(0xffffffff);
79 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
80
81 SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &fStencilBits);
82 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &fSampleCount);
83
84 SDL_GetWindowSize(fWindow, &fWidth, &fHeight);
85 glViewport(0, 0, fWidth, fHeight);
86 } else {
87 SkDebugf("MakeCurrent failed: %s\n", SDL_GetError());
88 }
89
90 // make the offscreen image
91 SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
92 kPremul_SkAlphaType, fDisplayParams.fColorSpace);
93 fBackbufferSurface = SkSurface::MakeRaster(info);
94 }
95
onDestroyContext()96 void RasterWindowContext_mac::onDestroyContext() {
97 if (!fWindow || !fGLContext) {
98 return;
99 }
100 fBackbufferSurface.reset(nullptr);
101 SDL_GL_DeleteContext(fGLContext);
102 fGLContext = nullptr;
103 }
104
getBackbufferSurface()105 sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
106
onSwapBuffers()107 void RasterWindowContext_mac::onSwapBuffers() {
108 if (fWindow && fGLContext) {
109 // We made/have an off-screen surface. Get the contents as an SkImage:
110 sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
111
112 sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface();
113 SkCanvas* gpuCanvas = gpuSurface->getCanvas();
114 gpuCanvas->drawImage(snapshot, 0, 0);
115 gpuCanvas->flush();
116
117 SDL_GL_SwapWindow(fWindow);
118 }
119 }
120
121 } // anonymous namespace
122
123 namespace sk_app {
124 namespace window_context_factory {
125
NewRasterForMac(const MacWindowInfo & info,const DisplayParams & params)126 WindowContext* NewRasterForMac(const MacWindowInfo& info, const DisplayParams& params) {
127 WindowContext* ctx = new RasterWindowContext_mac(info, params);
128 if (!ctx->isValid()) {
129 delete ctx;
130 return nullptr;
131 }
132 return ctx;
133 }
134
135 } // namespace window_context_factory
136 } // namespace sk_app
137