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