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