1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SurfaceMtl.h: Defines the class interface for Metal Surface.
7 
8 #ifndef LIBANGLE_RENDERER_METAL_SURFACEMTL_H_
9 #define LIBANGLE_RENDERER_METAL_SURFACEMTL_H_
10 
11 #import <Metal/Metal.h>
12 #import <QuartzCore/CALayer.h>
13 #import <QuartzCore/CAMetalLayer.h>
14 
15 #include "libANGLE/renderer/FramebufferImpl.h"
16 #include "libANGLE/renderer/SurfaceImpl.h"
17 #include "libANGLE/renderer/metal/RenderTargetMtl.h"
18 #include "libANGLE/renderer/metal/mtl_format_utils.h"
19 #include "libANGLE/renderer/metal/mtl_resources.h"
20 #include "libANGLE/renderer/metal/mtl_state_cache.h"
21 
22 namespace rx
23 {
24 
25 class DisplayMtl;
26 
27 class SurfaceMtl : public SurfaceImpl
28 {
29   public:
30     SurfaceMtl(DisplayMtl *display,
31                const egl::SurfaceState &state,
32                const egl::AttributeMap &attribs);
33     ~SurfaceMtl() override;
34 
35     void destroy(const egl::Display *display) override;
36 
37     egl::Error initialize(const egl::Display *display) override;
38     FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
39                                               const gl::FramebufferState &state) override;
40 
41     egl::Error makeCurrent(const gl::Context *context) override;
42     egl::Error unMakeCurrent(const gl::Context *context) override;
43     egl::Error swap(const gl::Context *context) override;
44     egl::Error postSubBuffer(const gl::Context *context,
45                              EGLint x,
46                              EGLint y,
47                              EGLint width,
48                              EGLint height) override;
49 
50     egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
51     egl::Error bindTexImage(const gl::Context *context,
52                             gl::Texture *texture,
53                             EGLint buffer) override;
54     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
55     egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
56     egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override;
57     void setSwapInterval(EGLint interval) override;
58     void setFixedWidth(EGLint width) override;
59     void setFixedHeight(EGLint height) override;
60 
61     EGLint getWidth() const override;
62     EGLint getHeight() const override;
63 
64     EGLint isPostSubBufferSupported() const override;
65     EGLint getSwapBehavior() const override;
66 
67     angle::Result initializeContents(const gl::Context *context,
68                                      const gl::ImageIndex &imageIndex) override;
69 
getColorTexture()70     const mtl::TextureRef &getColorTexture() { return mColorTexture; }
getColorFormat()71     const mtl::Format &getColorFormat() const { return mColorFormat; }
getSamples()72     int getSamples() const { return mSamples; }
73 
hasRobustResourceInit()74     bool hasRobustResourceInit() const { return mRobustResourceInit; }
75 
76     angle::Result getAttachmentRenderTarget(const gl::Context *context,
77                                             GLenum binding,
78                                             const gl::ImageIndex &imageIndex,
79                                             GLsizei samples,
80                                             FramebufferAttachmentRenderTarget **rtOut) override;
81 
82   protected:
83     // Ensure companion (MS, depth, stencil) textures' size is correct w.r.t color texture.
84     angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context,
85                                                      const gl::Extents &size);
86     angle::Result resolveColorTextureIfNeeded(const gl::Context *context);
87 
88     // Normal textures
89     mtl::TextureRef mColorTexture;
90     mtl::TextureRef mDepthTexture;
91     mtl::TextureRef mStencilTexture;
92 
93     // Implicit multisample texture
94     mtl::TextureRef mMSColorTexture;
95 
96     bool mUsePackedDepthStencil = false;
97     // Auto resolve MS texture at the end of render pass or requires a separate blitting pass?
98     bool mAutoResolveMSColorTexture = false;
99 
100     bool mRobustResourceInit = false;
101 
102     mtl::Format mColorFormat;
103     mtl::Format mDepthFormat;
104     mtl::Format mStencilFormat;
105 
106     int mSamples = 0;
107 
108     RenderTargetMtl mColorRenderTarget;
109     RenderTargetMtl mColorManualResolveRenderTarget;
110     RenderTargetMtl mDepthRenderTarget;
111     RenderTargetMtl mStencilRenderTarget;
112 };
113 
114 class WindowSurfaceMtl : public SurfaceMtl
115 {
116   public:
117     WindowSurfaceMtl(DisplayMtl *display,
118                      const egl::SurfaceState &state,
119                      EGLNativeWindowType window,
120                      const egl::AttributeMap &attribs);
121     ~WindowSurfaceMtl() override;
122 
123     void destroy(const egl::Display *display) override;
124 
125     egl::Error initialize(const egl::Display *display) override;
126     FramebufferImpl *createDefaultFramebuffer(const gl::Context *context,
127                                               const gl::FramebufferState &state) override;
128 
129     egl::Error swap(const gl::Context *context) override;
130 
131     void setSwapInterval(EGLint interval) override;
132     EGLint getSwapBehavior() const override;
133 
134     angle::Result initializeContents(const gl::Context *context,
135                                      const gl::ImageIndex &imageIndex) override;
136 
137     // width and height can change with client window resizing
138     EGLint getWidth() const override;
139     EGLint getHeight() const override;
140 
141     angle::Result getAttachmentRenderTarget(const gl::Context *context,
142                                             GLenum binding,
143                                             const gl::ImageIndex &imageIndex,
144                                             GLsizei samples,
145                                             FramebufferAttachmentRenderTarget **rtOut) override;
146 
147     angle::Result ensureCurrentDrawableObtained(const gl::Context *context,
148                                                 bool *newDrawableOut /** nullable */);
149 
150     // Ensure the the texture returned from getColorTexture() is ready for glReadPixels(). This
151     // implicitly calls ensureCurrentDrawableObtained().
152     angle::Result ensureColorTextureReadyForReadPixels(const gl::Context *context);
153 
154   private:
155     angle::Result swapImpl(const gl::Context *context);
156     angle::Result obtainNextDrawable(const gl::Context *context);
157     angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context);
158 
159     CGSize calcExpectedDrawableSize() const;
160     // Check if metal layer has been resized.
161     bool checkIfLayerResized(const gl::Context *context);
162 
163     mtl::AutoObjCObj<CAMetalLayer> mMetalLayer = nil;
164     CALayer *mLayer;
165     mtl::AutoObjCPtr<id<CAMetalDrawable>> mCurrentDrawable = nil;
166 
167     // Cache last known drawable size that is used by GL context. Can be used to detect resize
168     // event. We don't use mMetalLayer.drawableSize directly since it might be changed internally by
169     // metal runtime.
170     CGSize mCurrentKnownDrawableSize;
171 };
172 
173 // Offscreen surface, base class of PBuffer, IOSurface.
174 class OffscreenSurfaceMtl : public SurfaceMtl
175 {
176   public:
177     OffscreenSurfaceMtl(DisplayMtl *display,
178                         const egl::SurfaceState &state,
179                         const egl::AttributeMap &attribs);
180     ~OffscreenSurfaceMtl() override;
181 
182     void destroy(const egl::Display *display) override;
183 
184     egl::Error swap(const gl::Context *context) override;
185 
186     egl::Error bindTexImage(const gl::Context *context,
187                             gl::Texture *texture,
188                             EGLint buffer) override;
189     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
190 
191     angle::Result getAttachmentRenderTarget(const gl::Context *context,
192                                             GLenum binding,
193                                             const gl::ImageIndex &imageIndex,
194                                             GLsizei samples,
195                                             FramebufferAttachmentRenderTarget **rtOut) override;
196 
197   protected:
198     angle::Result ensureTexturesSizeCorrect(const gl::Context *context);
199 
200     gl::Extents mSize;
201 };
202 
203 // PBuffer surface
204 class PBufferSurfaceMtl : public OffscreenSurfaceMtl
205 {
206   public:
207     PBufferSurfaceMtl(DisplayMtl *display,
208                       const egl::SurfaceState &state,
209                       const egl::AttributeMap &attribs);
210 
211     void setFixedWidth(EGLint width) override;
212     void setFixedHeight(EGLint height) override;
213 };
214 
215 // Offscreen created from IOSurface
216 class IOSurfaceSurfaceMtl : public OffscreenSurfaceMtl
217 {
218   public:
219     IOSurfaceSurfaceMtl(DisplayMtl *display,
220                         const egl::SurfaceState &state,
221                         EGLClientBuffer buffer,
222                         const egl::AttributeMap &attribs);
223     ~IOSurfaceSurfaceMtl() override;
224 
225     egl::Error bindTexImage(const gl::Context *context,
226                             gl::Texture *texture,
227                             EGLint buffer) override;
228     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
229 
230     angle::Result getAttachmentRenderTarget(const gl::Context *context,
231                                             GLenum binding,
232                                             const gl::ImageIndex &imageIndex,
233                                             GLsizei samples,
234                                             FramebufferAttachmentRenderTarget **rtOut) override;
235 
236     static bool ValidateAttributes(EGLClientBuffer buffer, const egl::AttributeMap &attribs);
237 
238   private:
239     angle::Result ensureColorTextureCreated(const gl::Context *context);
240 
241     IOSurfaceRef mIOSurface;
242     NSUInteger mIOSurfacePlane;
243     int mIOSurfaceFormatIdx;
244 };
245 
246 }  // namespace rx
247 
248 #endif /* LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ */
249