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