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