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