xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/SurfaceMtl.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 #define ANGLE_TO_EGL_TRY(EXPR)                                 \
28     do                                                         \
29     {                                                          \
30         if (ANGLE_UNLIKELY((EXPR) != angle::Result::Continue)) \
31         {                                                      \
32             return egl::EglBadSurface();                       \
33         }                                                      \
34     } while (0)
35 
36 class SurfaceMtl : public SurfaceImpl
37 {
38   public:
39     SurfaceMtl(DisplayMtl *display,
40                const egl::SurfaceState &state,
41                const egl::AttributeMap &attribs);
42     ~SurfaceMtl() override;
43 
44     void destroy(const egl::Display *display) override;
45 
46     egl::Error initialize(const egl::Display *display) override;
47 
48     egl::Error makeCurrent(const gl::Context *context) override;
49     egl::Error unMakeCurrent(const gl::Context *context) override;
50     egl::Error swap(const gl::Context *context) override;
51     egl::Error postSubBuffer(const gl::Context *context,
52                              EGLint x,
53                              EGLint y,
54                              EGLint width,
55                              EGLint height) override;
56 
57     egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
58     egl::Error bindTexImage(const gl::Context *context,
59                             gl::Texture *texture,
60                             EGLint buffer) override;
61     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
62     egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
63     egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override;
64     void setSwapInterval(const egl::Display *display, EGLint interval) override;
65     void setFixedWidth(EGLint width) override;
66     void setFixedHeight(EGLint height) override;
67 
68     EGLint getWidth() const override;
69     EGLint getHeight() const override;
70 
71     EGLint isPostSubBufferSupported() const override;
72     EGLint getSwapBehavior() const override;
73 
74     angle::Result initializeContents(const gl::Context *context,
75                                      GLenum binding,
76                                      const gl::ImageIndex &imageIndex) override;
77 
getColorTexture()78     const mtl::TextureRef &getColorTexture() { return mColorTexture; }
getColorFormat()79     const mtl::Format &getColorFormat() const { return mColorFormat; }
getSamples()80     int getSamples() const { return mSamples; }
hasDepthStencil()81     bool hasDepthStencil() const { return mDepthTexture || mStencilTexture; }
82 
hasRobustResourceInit()83     bool hasRobustResourceInit() const { return mRobustResourceInit; }
84 
85     angle::Result getAttachmentRenderTarget(const gl::Context *context,
86                                             GLenum binding,
87                                             const gl::ImageIndex &imageIndex,
88                                             GLsizei samples,
89                                             FramebufferAttachmentRenderTarget **rtOut) override;
90     egl::Error attachToFramebuffer(const gl::Context *context,
91                                    gl::Framebuffer *framebuffer) override;
92     egl::Error detachFromFramebuffer(const gl::Context *context,
93                                      gl::Framebuffer *framebuffer) override;
94 
95   protected:
96     // Ensure companion (MS, depth, stencil) textures' size is correct w.r.t color texture.
97     angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context,
98                                                      const gl::Extents &size);
99     angle::Result resolveColorTextureIfNeeded(const gl::Context *context);
100 
101     // Normal textures
102     mtl::TextureRef mColorTexture;
103     mtl::TextureRef mDepthTexture;
104     mtl::TextureRef mStencilTexture;
105 
106     // Implicit multisample texture
107     mtl::TextureRef mMSColorTexture;
108 
109     bool mUsePackedDepthStencil = false;
110     // Auto resolve MS texture at the end of render pass or requires a separate blitting pass?
111     bool mAutoResolveMSColorTexture = false;
112 
113     bool mRobustResourceInit = false;
114     bool mColorTextureInitialized         = true;
115     bool mDepthStencilTexturesInitialized = true;
116 
117     mtl::Format mColorFormat;
118     mtl::Format mDepthFormat;
119     mtl::Format mStencilFormat;
120 
121     int mSamples = 0;
122 
123     RenderTargetMtl mColorRenderTarget;
124     RenderTargetMtl mColorManualResolveRenderTarget;
125     RenderTargetMtl mDepthRenderTarget;
126     RenderTargetMtl mStencilRenderTarget;
127 };
128 
129 class WindowSurfaceMtl : public SurfaceMtl
130 {
131   public:
132     WindowSurfaceMtl(DisplayMtl *display,
133                      const egl::SurfaceState &state,
134                      EGLNativeWindowType window,
135                      const egl::AttributeMap &attribs);
136     ~WindowSurfaceMtl() override;
137 
138     void destroy(const egl::Display *display) override;
139 
140     egl::Error initialize(const egl::Display *display) override;
141 
142     egl::Error swap(const gl::Context *context) override;
143 
144     void setSwapInterval(const egl::Display *display, EGLint interval) override;
145     EGLint getSwapBehavior() const override;
146 
147     angle::Result initializeContents(const gl::Context *context,
148                                      GLenum binding,
149                                      const gl::ImageIndex &imageIndex) override;
150 
151     // width and height can change with client window resizing
152     EGLint getWidth() const override;
153     EGLint getHeight() const override;
154     angle::Result getAttachmentRenderTarget(const gl::Context *context,
155                                             GLenum binding,
156                                             const gl::ImageIndex &imageIndex,
157                                             GLsizei samples,
158                                             FramebufferAttachmentRenderTarget **rtOut) override;
159     egl::Error attachToFramebuffer(const gl::Context *context,
160                                    gl::Framebuffer *framebuffer) override;
161     egl::Error detachFromFramebuffer(const gl::Context *context,
162                                      gl::Framebuffer *framebuffer) override;
163 
164     angle::Result ensureCurrentDrawableObtained(const gl::Context *context);
165 
166     // Ensure the the texture returned from getColorTexture() is ready for glReadPixels(). This
167     // implicitly calls ensureCurrentDrawableObtained().
168     angle::Result ensureColorTextureReadyForReadPixels(const gl::Context *context);
preserveBuffer()169     bool preserveBuffer() const { return mRetainBuffer; }
170 
171   private:
172     angle::Result swapImpl(const gl::Context *context);
173     angle::Result obtainNextDrawable(const gl::Context *context);
174     angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context);
175 
176     CGSize calcExpectedDrawableSize() const;
177     // Check if metal layer has been resized.
178     bool checkIfLayerResized(const gl::Context *context);
179 
180     mtl::AutoObjCObj<CAMetalLayer> mMetalLayer = nil;
181     CALayer *mLayer;
182     mtl::AutoObjCPtr<id<CAMetalDrawable>> mCurrentDrawable = nil;
183 
184     // Cache last known drawable size that is used by GL context. Can be used to detect resize
185     // event. We don't use mMetalLayer.drawableSize directly since it might be changed internally by
186     // metal runtime.
187     CGSize mCurrentKnownDrawableSize;
188 
189     bool mRetainBuffer = false;
190 };
191 
192 // Offscreen surface, base class of PBuffer.
193 class OffscreenSurfaceMtl : public SurfaceMtl
194 {
195   public:
196     OffscreenSurfaceMtl(DisplayMtl *display,
197                         const egl::SurfaceState &state,
198                         const egl::AttributeMap &attribs);
199     ~OffscreenSurfaceMtl() override;
200 
201     void destroy(const egl::Display *display) override;
202 
203     EGLint getWidth() const override;
204     EGLint getHeight() const override;
205 
206     egl::Error swap(const gl::Context *context) override;
207 
208     egl::Error bindTexImage(const gl::Context *context,
209                             gl::Texture *texture,
210                             EGLint buffer) override;
211     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
212 
213     angle::Result getAttachmentRenderTarget(const gl::Context *context,
214                                             GLenum binding,
215                                             const gl::ImageIndex &imageIndex,
216                                             GLsizei samples,
217                                             FramebufferAttachmentRenderTarget **rtOut) override;
218 
219   protected:
220     angle::Result ensureTexturesSizeCorrect(const gl::Context *context);
221 
222     gl::Extents mSize;
223 };
224 
225 // PBuffer surface
226 class PBufferSurfaceMtl : public OffscreenSurfaceMtl
227 {
228   public:
229     PBufferSurfaceMtl(DisplayMtl *display,
230                       const egl::SurfaceState &state,
231                       const egl::AttributeMap &attribs);
232 
233     void setFixedWidth(EGLint width) override;
234     void setFixedHeight(EGLint height) override;
235 };
236 
237 }  // namespace rx
238 #endif /* LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ */
239