• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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