Flutter Engine
The Flutter Engine
RasterWindowContext_mac.mm
Go to the documentation of this file.
1
2/*
3 * Copyright 2019 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
13#include "tools/ToolUtils.h"
17
18#include <OpenGL/gl.h>
19
20#include <Cocoa/Cocoa.h>
21
25
26namespace {
27
28// TODO: This still uses GL to handle the update rather than using a purely raster backend,
29// for historical reasons. Writing a pure raster backend would be better in the long run.
30
31class RasterWindowContext_mac : public GLWindowContext {
32public:
33 RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
34
35 ~RasterWindowContext_mac() override;
36
38
40 void onDestroyContext() override {}
41
42 void resize(int w, int h) override;
43
44private:
45 void onSwapBuffers() override;
46
47 NSView* fMainView;
48 NSOpenGLContext* fGLContext;
49 NSOpenGLPixelFormat* fPixelFormat;
50 sk_sp<SkSurface> fBackbufferSurface;
51};
52
53RasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
54 const DisplayParams& params)
56 , fMainView(info.fMainView)
57 , fGLContext(nil) {
58
59 // any config code here (particularly for msaa)?
60
61 this->initializeContext();
62}
63
64RasterWindowContext_mac::~RasterWindowContext_mac() {
65 [NSOpenGLContext clearCurrentContext];
66 [fPixelFormat release];
67 fPixelFormat = nil;
68 [fGLContext release];
69 fGLContext = nil;
70}
71
72sk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
73 SkASSERT(nil != fMainView);
74
75 if (!fGLContext) {
76 // set up pixel format
77 constexpr int kMaxAttributes = 18;
78 NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
79 int numAttributes = 0;
80 attributes[numAttributes++] = NSOpenGLPFAAccelerated;
81 attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
82 attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
83 attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
84 attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
85 attributes[numAttributes++] = NSOpenGLPFAColorSize;
86 attributes[numAttributes++] = 24;
87 attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
88 attributes[numAttributes++] = 8;
89 attributes[numAttributes++] = NSOpenGLPFADepthSize;
90 attributes[numAttributes++] = 0;
91 attributes[numAttributes++] = NSOpenGLPFAStencilSize;
92 attributes[numAttributes++] = 8;
93 if (fDisplayParams.fMSAASampleCount > 1) {
94 attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
95 attributes[numAttributes++] = 1;
96 attributes[numAttributes++] = NSOpenGLPFASamples;
97 attributes[numAttributes++] = fDisplayParams.fMSAASampleCount;
98 } else {
99 attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
100 attributes[numAttributes++] = 0;
101 }
102 attributes[numAttributes++] = 0;
103 SkASSERT(numAttributes <= kMaxAttributes);
104
105 fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
106 if (nil == fPixelFormat) {
107 return nullptr;
108 }
109
110 // create context
111 fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
112 if (nil == fGLContext) {
113 [fPixelFormat release];
114 fPixelFormat = nil;
115 return nullptr;
116 }
117
118 [fMainView setWantsBestResolutionOpenGLSurface:YES];
119 [fGLContext setView:fMainView];
120
121 GLint swapInterval = fDisplayParams.fDisableVsync ? 0 : 1;
122 [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
123 }
124
125 // make context current
126 [fGLContext makeCurrentContext];
127
128 glClearStencil(0);
129 glClearColor(0, 0, 0, 255);
130 glStencilMask(0xffffffff);
131 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
132
133 GLint stencilBits;
134 [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
135 fStencilBits = stencilBits;
136 GLint sampleCount;
137 [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
138 fSampleCount = sampleCount;
139 fSampleCount = std::max(fSampleCount, 1);
140
141 CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView);
142 fWidth = fMainView.bounds.size.width * backingScaleFactor;
143 fHeight = fMainView.bounds.size.height * backingScaleFactor;
144 glViewport(0, 0, fWidth, fHeight);
145
146 // make the offscreen image
147 SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType,
148 kPremul_SkAlphaType, fDisplayParams.fColorSpace);
149 fBackbufferSurface = SkSurfaces::Raster(info);
151}
152
153sk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
154
155void RasterWindowContext_mac::onSwapBuffers() {
156 if (fBackbufferSurface) {
157 // We made/have an off-screen surface. Get the contents as an SkImage:
158 sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
159
160 sk_sp<SkSurface> gpuSurface = GLWindowContext::getBackbufferSurface();
161 SkCanvas* gpuCanvas = gpuSurface->getCanvas();
162 gpuCanvas->drawImage(snapshot, 0, 0);
163 skgpu::ganesh::Flush(gpuSurface);
164
165 [fGLContext flushBuffer];
166 }
167}
168
169void RasterWindowContext_mac::resize(int w, int h) {
170 [fGLContext update];
171
172 // The super class always recreates the context.
173 GLWindowContext::resize(0, 0);
174}
175
176} // anonymous namespace
177
178namespace skwindow {
179
180std::unique_ptr<WindowContext> MakeRasterForMac(const MacWindowInfo& info,
181 const DisplayParams& params) {
182 std::unique_ptr<WindowContext> ctx(new RasterWindowContext_mac(info, params));
183 if (!ctx->isValid()) {
184 return nullptr;
185 }
186 return ctx;
187}
188
189} // namespace skwindow
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
virtual void onSwapBuffers()=0
void resize(int w, int h) override
virtual sk_sp< const GrGLInterface > onInitializeContext()=0
sk_sp< SkSurface > getBackbufferSurface() override
const EmbeddedViewParams * params
static float max(float r, float g, float b)
Definition: hsl.cpp:49
SK_API sk_sp< const GrGLInterface > MakeMac()
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API GrSemaphoresSubmitted Flush(sk_sp< SkSurface >)
std::unique_ptr< WindowContext > MakeRasterForMac(const MacWindowInfo &info, const DisplayParams &params)
static CGFloat GetBackingScaleFactor(NSView *view)
Definition: update.py:1
SkScalar w
SkScalar h
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)