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