• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(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 mContentInitialized = false;
115 
116     mtl::Format mColorFormat;
117     mtl::Format mDepthFormat;
118     mtl::Format mStencilFormat;
119 
120     int mSamples = 0;
121 
122     RenderTargetMtl mColorRenderTarget;
123     RenderTargetMtl mColorManualResolveRenderTarget;
124     RenderTargetMtl mDepthRenderTarget;
125     RenderTargetMtl mStencilRenderTarget;
126 };
127 
128 class WindowSurfaceMtl : public SurfaceMtl
129 {
130   public:
131     WindowSurfaceMtl(DisplayMtl *display,
132                      const egl::SurfaceState &state,
133                      EGLNativeWindowType window,
134                      const egl::AttributeMap &attribs);
135     ~WindowSurfaceMtl() override;
136 
137     void destroy(const egl::Display *display) override;
138 
139     egl::Error initialize(const egl::Display *display) override;
140 
141     egl::Error swap(const gl::Context *context) override;
142 
143     void setSwapInterval(EGLint interval) override;
144     EGLint getSwapBehavior() const override;
145 
146     angle::Result initializeContents(const gl::Context *context,
147                                      GLenum binding,
148                                      const gl::ImageIndex &imageIndex) override;
149 
150     // width and height can change with client window resizing
151     EGLint getWidth() const override;
152     EGLint getHeight() const override;
153     angle::Result getAttachmentRenderTarget(const gl::Context *context,
154                                             GLenum binding,
155                                             const gl::ImageIndex &imageIndex,
156                                             GLsizei samples,
157                                             FramebufferAttachmentRenderTarget **rtOut) override;
158     egl::Error attachToFramebuffer(const gl::Context *context,
159                                    gl::Framebuffer *framebuffer) override;
160     egl::Error detachFromFramebuffer(const gl::Context *context,
161                                      gl::Framebuffer *framebuffer) override;
162 
163     angle::Result ensureCurrentDrawableObtained(const gl::Context *context);
164 
165     // Ensure the the texture returned from getColorTexture() is ready for glReadPixels(). This
166     // implicitly calls ensureCurrentDrawableObtained().
167     angle::Result ensureColorTextureReadyForReadPixels(const gl::Context *context);
preserveBuffer()168     bool preserveBuffer() const { return mRetainBuffer; }
169 
170   private:
171     angle::Result swapImpl(const gl::Context *context);
172     angle::Result obtainNextDrawable(const gl::Context *context);
173     angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context);
174 
175     CGSize calcExpectedDrawableSize() const;
176     // Check if metal layer has been resized.
177     bool checkIfLayerResized(const gl::Context *context);
178 
179     mtl::AutoObjCObj<CAMetalLayer> mMetalLayer = nil;
180     CALayer *mLayer;
181     mtl::AutoObjCPtr<id<CAMetalDrawable>> mCurrentDrawable = nil;
182 
183     // Cache last known drawable size that is used by GL context. Can be used to detect resize
184     // event. We don't use mMetalLayer.drawableSize directly since it might be changed internally by
185     // metal runtime.
186     CGSize mCurrentKnownDrawableSize;
187 
188     bool mRetainBuffer = false;
189 };
190 
191 // Offscreen surface, base class of PBuffer.
192 class OffscreenSurfaceMtl : public SurfaceMtl
193 {
194   public:
195     OffscreenSurfaceMtl(DisplayMtl *display,
196                         const egl::SurfaceState &state,
197                         const egl::AttributeMap &attribs);
198     ~OffscreenSurfaceMtl() override;
199 
200     void destroy(const egl::Display *display) override;
201 
202     EGLint getWidth() const override;
203     EGLint getHeight() const override;
204 
205     egl::Error swap(const gl::Context *context) override;
206 
207     egl::Error bindTexImage(const gl::Context *context,
208                             gl::Texture *texture,
209                             EGLint buffer) override;
210     egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
211 
212     angle::Result getAttachmentRenderTarget(const gl::Context *context,
213                                             GLenum binding,
214                                             const gl::ImageIndex &imageIndex,
215                                             GLsizei samples,
216                                             FramebufferAttachmentRenderTarget **rtOut) override;
217 
218   protected:
219     angle::Result ensureTexturesSizeCorrect(const gl::Context *context);
220 
221     gl::Extents mSize;
222 };
223 
224 // PBuffer surface
225 class PBufferSurfaceMtl : public OffscreenSurfaceMtl
226 {
227   public:
228     PBufferSurfaceMtl(DisplayMtl *display,
229                       const egl::SurfaceState &state,
230                       const egl::AttributeMap &attribs);
231 
232     void setFixedWidth(EGLint width) override;
233     void setFixedHeight(EGLint height) override;
234 };
235 
236 }  // namespace rx
237 #endif /* LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ */
238