xref: /aosp_15_r20/external/skia/tools/window/mac/RasterWindowContext_mac.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker/*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2019 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker#include "tools/window/mac/RasterWindowContext_mac.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker#include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker#include "include/core/SkColorFilter.h"
12*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/SkSurfaceGanesh.h"
13*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/gl/mac/GrGLMakeMacInterface.h"
14*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/gl/GrGLInterface.h"
15*c8dee2aaSAndroid Build Coastguard Worker#include "tools/ToolUtils.h"
16*c8dee2aaSAndroid Build Coastguard Worker#include "tools/window/GLWindowContext.h"
17*c8dee2aaSAndroid Build Coastguard Worker#include "tools/window/mac/MacWindowInfo.h"
18*c8dee2aaSAndroid Build Coastguard Worker
19*c8dee2aaSAndroid Build Coastguard Worker#include <OpenGL/gl.h>
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Worker#include <Cocoa/Cocoa.h>
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Workerusing skwindow::DisplayParams;
24*c8dee2aaSAndroid Build Coastguard Workerusing skwindow::MacWindowInfo;
25*c8dee2aaSAndroid Build Coastguard Workerusing skwindow::internal::GLWindowContext;
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Workernamespace {
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker// TODO: This still uses GL to handle the update rather than using a purely raster backend,
30*c8dee2aaSAndroid Build Coastguard Worker// for historical reasons. Writing a pure raster backend would be better in the long run.
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Workerclass RasterWindowContext_mac : public GLWindowContext {
33*c8dee2aaSAndroid Build Coastguard Workerpublic:
34*c8dee2aaSAndroid Build Coastguard Worker    RasterWindowContext_mac(const MacWindowInfo&, std::unique_ptr<const DisplayParams>);
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker    ~RasterWindowContext_mac() override;
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<SkSurface> getBackbufferSurface() override;
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<const GrGLInterface> onInitializeContext() override;
41*c8dee2aaSAndroid Build Coastguard Worker    void onDestroyContext() override {}
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker    void resize(int w, int h) override;
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Workerprivate:
46*c8dee2aaSAndroid Build Coastguard Worker    void onSwapBuffers() override;
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker    NSView*              fMainView;
49*c8dee2aaSAndroid Build Coastguard Worker    NSOpenGLContext*     fGLContext;
50*c8dee2aaSAndroid Build Coastguard Worker    NSOpenGLPixelFormat* fPixelFormat;
51*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<SkSurface>     fBackbufferSurface;
52*c8dee2aaSAndroid Build Coastguard Worker};
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard WorkerRasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info,
55*c8dee2aaSAndroid Build Coastguard Worker                                                 std::unique_ptr<const DisplayParams> params)
56*c8dee2aaSAndroid Build Coastguard Worker        : GLWindowContext(std::move(params)), fMainView(info.fMainView), fGLContext(nil) {
57*c8dee2aaSAndroid Build Coastguard Worker    // any config code here (particularly for msaa)?
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker    this->initializeContext();
60*c8dee2aaSAndroid Build Coastguard Worker}
61*c8dee2aaSAndroid Build Coastguard Worker
62*c8dee2aaSAndroid Build Coastguard WorkerRasterWindowContext_mac::~RasterWindowContext_mac() {
63*c8dee2aaSAndroid Build Coastguard Worker    [NSOpenGLContext clearCurrentContext];
64*c8dee2aaSAndroid Build Coastguard Worker    [fPixelFormat release];
65*c8dee2aaSAndroid Build Coastguard Worker    fPixelFormat = nil;
66*c8dee2aaSAndroid Build Coastguard Worker    [fGLContext release];
67*c8dee2aaSAndroid Build Coastguard Worker    fGLContext = nil;
68*c8dee2aaSAndroid Build Coastguard Worker}
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Workersk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() {
71*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(nil != fMainView);
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker    if (!fGLContext) {
74*c8dee2aaSAndroid Build Coastguard Worker        // set up pixel format
75*c8dee2aaSAndroid Build Coastguard Worker        constexpr int kMaxAttributes = 18;
76*c8dee2aaSAndroid Build Coastguard Worker        NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
77*c8dee2aaSAndroid Build Coastguard Worker        int numAttributes = 0;
78*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAAccelerated;
79*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
80*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
81*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
82*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
83*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAColorSize;
84*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = 24;
85*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
86*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = 8;
87*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFADepthSize;
88*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = 0;
89*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = NSOpenGLPFAStencilSize;
90*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = 8;
91*c8dee2aaSAndroid Build Coastguard Worker        if (fDisplayParams->msaaSampleCount() > 1) {
92*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
93*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = 1;
94*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = NSOpenGLPFASamples;
95*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = fDisplayParams->msaaSampleCount();
96*c8dee2aaSAndroid Build Coastguard Worker        } else {
97*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
98*c8dee2aaSAndroid Build Coastguard Worker            attributes[numAttributes++] = 0;
99*c8dee2aaSAndroid Build Coastguard Worker        }
100*c8dee2aaSAndroid Build Coastguard Worker        attributes[numAttributes++] = 0;
101*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(numAttributes <= kMaxAttributes);
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker        fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
104*c8dee2aaSAndroid Build Coastguard Worker        if (nil == fPixelFormat) {
105*c8dee2aaSAndroid Build Coastguard Worker            return nullptr;
106*c8dee2aaSAndroid Build Coastguard Worker        }
107*c8dee2aaSAndroid Build Coastguard Worker
108*c8dee2aaSAndroid Build Coastguard Worker        // create context
109*c8dee2aaSAndroid Build Coastguard Worker        fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
110*c8dee2aaSAndroid Build Coastguard Worker        if (nil == fGLContext) {
111*c8dee2aaSAndroid Build Coastguard Worker            [fPixelFormat release];
112*c8dee2aaSAndroid Build Coastguard Worker            fPixelFormat = nil;
113*c8dee2aaSAndroid Build Coastguard Worker            return nullptr;
114*c8dee2aaSAndroid Build Coastguard Worker        }
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker        [fMainView setWantsBestResolutionOpenGLSurface:YES];
117*c8dee2aaSAndroid Build Coastguard Worker        [fGLContext setView:fMainView];
118*c8dee2aaSAndroid Build Coastguard Worker
119*c8dee2aaSAndroid Build Coastguard Worker        GLint swapInterval = fDisplayParams->disableVsync() ? 0 : 1;
120*c8dee2aaSAndroid Build Coastguard Worker        [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
121*c8dee2aaSAndroid Build Coastguard Worker    }
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker    // make context current
124*c8dee2aaSAndroid Build Coastguard Worker    [fGLContext makeCurrentContext];
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker    glClearStencil(0);
127*c8dee2aaSAndroid Build Coastguard Worker    glClearColor(0, 0, 0, 255);
128*c8dee2aaSAndroid Build Coastguard Worker    glStencilMask(0xffffffff);
129*c8dee2aaSAndroid Build Coastguard Worker    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker    GLint stencilBits;
132*c8dee2aaSAndroid Build Coastguard Worker    [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
133*c8dee2aaSAndroid Build Coastguard Worker    fStencilBits = stencilBits;
134*c8dee2aaSAndroid Build Coastguard Worker    GLint sampleCount;
135*c8dee2aaSAndroid Build Coastguard Worker    [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
136*c8dee2aaSAndroid Build Coastguard Worker    fSampleCount = sampleCount;
137*c8dee2aaSAndroid Build Coastguard Worker    fSampleCount = std::max(fSampleCount, 1);
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker    CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView);
140*c8dee2aaSAndroid Build Coastguard Worker    fWidth = fMainView.bounds.size.width * backingScaleFactor;
141*c8dee2aaSAndroid Build Coastguard Worker    fHeight = fMainView.bounds.size.height * backingScaleFactor;
142*c8dee2aaSAndroid Build Coastguard Worker    glViewport(0, 0, fWidth, fHeight);
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker    // make the offscreen image
145*c8dee2aaSAndroid Build Coastguard Worker    SkImageInfo info = SkImageInfo::Make(fWidth,
146*c8dee2aaSAndroid Build Coastguard Worker                                         fHeight,
147*c8dee2aaSAndroid Build Coastguard Worker                                         fDisplayParams->colorType(),
148*c8dee2aaSAndroid Build Coastguard Worker                                         kPremul_SkAlphaType,
149*c8dee2aaSAndroid Build Coastguard Worker                                         fDisplayParams->colorSpace());
150*c8dee2aaSAndroid Build Coastguard Worker    fBackbufferSurface = SkSurfaces::Raster(info);
151*c8dee2aaSAndroid Build Coastguard Worker    return GrGLInterfaces::MakeMac();
152*c8dee2aaSAndroid Build Coastguard Worker}
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Workersk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; }
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Workervoid RasterWindowContext_mac::onSwapBuffers() {
157*c8dee2aaSAndroid Build Coastguard Worker    if (fBackbufferSurface) {
158*c8dee2aaSAndroid Build Coastguard Worker        // We made/have an off-screen surface. Get the contents as an SkImage:
159*c8dee2aaSAndroid Build Coastguard Worker        sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot();
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker        sk_sp<SkSurface> gpuSurface = GLWindowContext::getBackbufferSurface();
162*c8dee2aaSAndroid Build Coastguard Worker        SkCanvas* gpuCanvas = gpuSurface->getCanvas();
163*c8dee2aaSAndroid Build Coastguard Worker        gpuCanvas->drawImage(snapshot, 0, 0);
164*c8dee2aaSAndroid Build Coastguard Worker        skgpu::ganesh::Flush(gpuSurface);
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker        [fGLContext flushBuffer];
167*c8dee2aaSAndroid Build Coastguard Worker    }
168*c8dee2aaSAndroid Build Coastguard Worker}
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Workervoid RasterWindowContext_mac::resize(int w, int h) {
171*c8dee2aaSAndroid Build Coastguard Worker    [fGLContext update];
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker    // The super class always recreates the context.
174*c8dee2aaSAndroid Build Coastguard Worker    GLWindowContext::resize(0, 0);
175*c8dee2aaSAndroid Build Coastguard Worker}
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker}  // anonymous namespace
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Workernamespace skwindow {
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Workerstd::unique_ptr<WindowContext> MakeRasterForMac(const MacWindowInfo& info,
182*c8dee2aaSAndroid Build Coastguard Worker                                                std::unique_ptr<const DisplayParams> params) {
183*c8dee2aaSAndroid Build Coastguard Worker    std::unique_ptr<WindowContext> ctx(new RasterWindowContext_mac(info, std::move(params)));
184*c8dee2aaSAndroid Build Coastguard Worker    if (!ctx->isValid()) {
185*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
186*c8dee2aaSAndroid Build Coastguard Worker    }
187*c8dee2aaSAndroid Build Coastguard Worker    return ctx;
188*c8dee2aaSAndroid Build Coastguard Worker}
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker}  // namespace skwindow
191