1*8975f5c5SAndroid Build Coastguard Worker // 2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2019 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker // 6*8975f5c5SAndroid Build Coastguard Worker // SurfaceMtl.h: Defines the class interface for Metal Surface. 7*8975f5c5SAndroid Build Coastguard Worker 8*8975f5c5SAndroid Build Coastguard Worker #ifndef LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ 9*8975f5c5SAndroid Build Coastguard Worker #define LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ 10*8975f5c5SAndroid Build Coastguard Worker 11*8975f5c5SAndroid Build Coastguard Worker #import <Metal/Metal.h> 12*8975f5c5SAndroid Build Coastguard Worker #import <QuartzCore/CALayer.h> 13*8975f5c5SAndroid Build Coastguard Worker #import <QuartzCore/CAMetalLayer.h> 14*8975f5c5SAndroid Build Coastguard Worker 15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/FramebufferImpl.h" 16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/SurfaceImpl.h" 17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/RenderTargetMtl.h" 18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_format_utils.h" 19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_resources.h" 20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/metal/mtl_state_cache.h" 21*8975f5c5SAndroid Build Coastguard Worker 22*8975f5c5SAndroid Build Coastguard Worker namespace rx 23*8975f5c5SAndroid Build Coastguard Worker { 24*8975f5c5SAndroid Build Coastguard Worker 25*8975f5c5SAndroid Build Coastguard Worker class DisplayMtl; 26*8975f5c5SAndroid Build Coastguard Worker 27*8975f5c5SAndroid Build Coastguard Worker #define ANGLE_TO_EGL_TRY(EXPR) \ 28*8975f5c5SAndroid Build Coastguard Worker do \ 29*8975f5c5SAndroid Build Coastguard Worker { \ 30*8975f5c5SAndroid Build Coastguard Worker if (ANGLE_UNLIKELY((EXPR) != angle::Result::Continue)) \ 31*8975f5c5SAndroid Build Coastguard Worker { \ 32*8975f5c5SAndroid Build Coastguard Worker return egl::EglBadSurface(); \ 33*8975f5c5SAndroid Build Coastguard Worker } \ 34*8975f5c5SAndroid Build Coastguard Worker } while (0) 35*8975f5c5SAndroid Build Coastguard Worker 36*8975f5c5SAndroid Build Coastguard Worker class SurfaceMtl : public SurfaceImpl 37*8975f5c5SAndroid Build Coastguard Worker { 38*8975f5c5SAndroid Build Coastguard Worker public: 39*8975f5c5SAndroid Build Coastguard Worker SurfaceMtl(DisplayMtl *display, 40*8975f5c5SAndroid Build Coastguard Worker const egl::SurfaceState &state, 41*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs); 42*8975f5c5SAndroid Build Coastguard Worker ~SurfaceMtl() override; 43*8975f5c5SAndroid Build Coastguard Worker 44*8975f5c5SAndroid Build Coastguard Worker void destroy(const egl::Display *display) override; 45*8975f5c5SAndroid Build Coastguard Worker 46*8975f5c5SAndroid Build Coastguard Worker egl::Error initialize(const egl::Display *display) override; 47*8975f5c5SAndroid Build Coastguard Worker 48*8975f5c5SAndroid Build Coastguard Worker egl::Error makeCurrent(const gl::Context *context) override; 49*8975f5c5SAndroid Build Coastguard Worker egl::Error unMakeCurrent(const gl::Context *context) override; 50*8975f5c5SAndroid Build Coastguard Worker egl::Error swap(const gl::Context *context) override; 51*8975f5c5SAndroid Build Coastguard Worker egl::Error postSubBuffer(const gl::Context *context, 52*8975f5c5SAndroid Build Coastguard Worker EGLint x, 53*8975f5c5SAndroid Build Coastguard Worker EGLint y, 54*8975f5c5SAndroid Build Coastguard Worker EGLint width, 55*8975f5c5SAndroid Build Coastguard Worker EGLint height) override; 56*8975f5c5SAndroid Build Coastguard Worker 57*8975f5c5SAndroid Build Coastguard Worker egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; 58*8975f5c5SAndroid Build Coastguard Worker egl::Error bindTexImage(const gl::Context *context, 59*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture, 60*8975f5c5SAndroid Build Coastguard Worker EGLint buffer) override; 61*8975f5c5SAndroid Build Coastguard Worker egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; 62*8975f5c5SAndroid Build Coastguard Worker egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; 63*8975f5c5SAndroid Build Coastguard Worker egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override; 64*8975f5c5SAndroid Build Coastguard Worker void setSwapInterval(const egl::Display *display, EGLint interval) override; 65*8975f5c5SAndroid Build Coastguard Worker void setFixedWidth(EGLint width) override; 66*8975f5c5SAndroid Build Coastguard Worker void setFixedHeight(EGLint height) override; 67*8975f5c5SAndroid Build Coastguard Worker 68*8975f5c5SAndroid Build Coastguard Worker EGLint getWidth() const override; 69*8975f5c5SAndroid Build Coastguard Worker EGLint getHeight() const override; 70*8975f5c5SAndroid Build Coastguard Worker 71*8975f5c5SAndroid Build Coastguard Worker EGLint isPostSubBufferSupported() const override; 72*8975f5c5SAndroid Build Coastguard Worker EGLint getSwapBehavior() const override; 73*8975f5c5SAndroid Build Coastguard Worker 74*8975f5c5SAndroid Build Coastguard Worker angle::Result initializeContents(const gl::Context *context, 75*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 76*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex) override; 77*8975f5c5SAndroid Build Coastguard Worker getColorTexture()78*8975f5c5SAndroid Build Coastguard Worker const mtl::TextureRef &getColorTexture() { return mColorTexture; } getColorFormat()79*8975f5c5SAndroid Build Coastguard Worker const mtl::Format &getColorFormat() const { return mColorFormat; } getSamples()80*8975f5c5SAndroid Build Coastguard Worker int getSamples() const { return mSamples; } hasDepthStencil()81*8975f5c5SAndroid Build Coastguard Worker bool hasDepthStencil() const { return mDepthTexture || mStencilTexture; } 82*8975f5c5SAndroid Build Coastguard Worker hasRobustResourceInit()83*8975f5c5SAndroid Build Coastguard Worker bool hasRobustResourceInit() const { return mRobustResourceInit; } 84*8975f5c5SAndroid Build Coastguard Worker 85*8975f5c5SAndroid Build Coastguard Worker angle::Result getAttachmentRenderTarget(const gl::Context *context, 86*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 87*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex, 88*8975f5c5SAndroid Build Coastguard Worker GLsizei samples, 89*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentRenderTarget **rtOut) override; 90*8975f5c5SAndroid Build Coastguard Worker egl::Error attachToFramebuffer(const gl::Context *context, 91*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *framebuffer) override; 92*8975f5c5SAndroid Build Coastguard Worker egl::Error detachFromFramebuffer(const gl::Context *context, 93*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *framebuffer) override; 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker protected: 96*8975f5c5SAndroid Build Coastguard Worker // Ensure companion (MS, depth, stencil) textures' size is correct w.r.t color texture. 97*8975f5c5SAndroid Build Coastguard Worker angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context, 98*8975f5c5SAndroid Build Coastguard Worker const gl::Extents &size); 99*8975f5c5SAndroid Build Coastguard Worker angle::Result resolveColorTextureIfNeeded(const gl::Context *context); 100*8975f5c5SAndroid Build Coastguard Worker 101*8975f5c5SAndroid Build Coastguard Worker // Normal textures 102*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef mColorTexture; 103*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef mDepthTexture; 104*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef mStencilTexture; 105*8975f5c5SAndroid Build Coastguard Worker 106*8975f5c5SAndroid Build Coastguard Worker // Implicit multisample texture 107*8975f5c5SAndroid Build Coastguard Worker mtl::TextureRef mMSColorTexture; 108*8975f5c5SAndroid Build Coastguard Worker 109*8975f5c5SAndroid Build Coastguard Worker bool mUsePackedDepthStencil = false; 110*8975f5c5SAndroid Build Coastguard Worker // Auto resolve MS texture at the end of render pass or requires a separate blitting pass? 111*8975f5c5SAndroid Build Coastguard Worker bool mAutoResolveMSColorTexture = false; 112*8975f5c5SAndroid Build Coastguard Worker 113*8975f5c5SAndroid Build Coastguard Worker bool mRobustResourceInit = false; 114*8975f5c5SAndroid Build Coastguard Worker bool mColorTextureInitialized = true; 115*8975f5c5SAndroid Build Coastguard Worker bool mDepthStencilTexturesInitialized = true; 116*8975f5c5SAndroid Build Coastguard Worker 117*8975f5c5SAndroid Build Coastguard Worker mtl::Format mColorFormat; 118*8975f5c5SAndroid Build Coastguard Worker mtl::Format mDepthFormat; 119*8975f5c5SAndroid Build Coastguard Worker mtl::Format mStencilFormat; 120*8975f5c5SAndroid Build Coastguard Worker 121*8975f5c5SAndroid Build Coastguard Worker int mSamples = 0; 122*8975f5c5SAndroid Build Coastguard Worker 123*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl mColorRenderTarget; 124*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl mColorManualResolveRenderTarget; 125*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl mDepthRenderTarget; 126*8975f5c5SAndroid Build Coastguard Worker RenderTargetMtl mStencilRenderTarget; 127*8975f5c5SAndroid Build Coastguard Worker }; 128*8975f5c5SAndroid Build Coastguard Worker 129*8975f5c5SAndroid Build Coastguard Worker class WindowSurfaceMtl : public SurfaceMtl 130*8975f5c5SAndroid Build Coastguard Worker { 131*8975f5c5SAndroid Build Coastguard Worker public: 132*8975f5c5SAndroid Build Coastguard Worker WindowSurfaceMtl(DisplayMtl *display, 133*8975f5c5SAndroid Build Coastguard Worker const egl::SurfaceState &state, 134*8975f5c5SAndroid Build Coastguard Worker EGLNativeWindowType window, 135*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs); 136*8975f5c5SAndroid Build Coastguard Worker ~WindowSurfaceMtl() override; 137*8975f5c5SAndroid Build Coastguard Worker 138*8975f5c5SAndroid Build Coastguard Worker void destroy(const egl::Display *display) override; 139*8975f5c5SAndroid Build Coastguard Worker 140*8975f5c5SAndroid Build Coastguard Worker egl::Error initialize(const egl::Display *display) override; 141*8975f5c5SAndroid Build Coastguard Worker 142*8975f5c5SAndroid Build Coastguard Worker egl::Error swap(const gl::Context *context) override; 143*8975f5c5SAndroid Build Coastguard Worker 144*8975f5c5SAndroid Build Coastguard Worker void setSwapInterval(const egl::Display *display, EGLint interval) override; 145*8975f5c5SAndroid Build Coastguard Worker EGLint getSwapBehavior() const override; 146*8975f5c5SAndroid Build Coastguard Worker 147*8975f5c5SAndroid Build Coastguard Worker angle::Result initializeContents(const gl::Context *context, 148*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 149*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex) override; 150*8975f5c5SAndroid Build Coastguard Worker 151*8975f5c5SAndroid Build Coastguard Worker // width and height can change with client window resizing 152*8975f5c5SAndroid Build Coastguard Worker EGLint getWidth() const override; 153*8975f5c5SAndroid Build Coastguard Worker EGLint getHeight() const override; 154*8975f5c5SAndroid Build Coastguard Worker angle::Result getAttachmentRenderTarget(const gl::Context *context, 155*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 156*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex, 157*8975f5c5SAndroid Build Coastguard Worker GLsizei samples, 158*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentRenderTarget **rtOut) override; 159*8975f5c5SAndroid Build Coastguard Worker egl::Error attachToFramebuffer(const gl::Context *context, 160*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *framebuffer) override; 161*8975f5c5SAndroid Build Coastguard Worker egl::Error detachFromFramebuffer(const gl::Context *context, 162*8975f5c5SAndroid Build Coastguard Worker gl::Framebuffer *framebuffer) override; 163*8975f5c5SAndroid Build Coastguard Worker 164*8975f5c5SAndroid Build Coastguard Worker angle::Result ensureCurrentDrawableObtained(const gl::Context *context); 165*8975f5c5SAndroid Build Coastguard Worker 166*8975f5c5SAndroid Build Coastguard Worker // Ensure the the texture returned from getColorTexture() is ready for glReadPixels(). This 167*8975f5c5SAndroid Build Coastguard Worker // implicitly calls ensureCurrentDrawableObtained(). 168*8975f5c5SAndroid Build Coastguard Worker angle::Result ensureColorTextureReadyForReadPixels(const gl::Context *context); preserveBuffer()169*8975f5c5SAndroid Build Coastguard Worker bool preserveBuffer() const { return mRetainBuffer; } 170*8975f5c5SAndroid Build Coastguard Worker 171*8975f5c5SAndroid Build Coastguard Worker private: 172*8975f5c5SAndroid Build Coastguard Worker angle::Result swapImpl(const gl::Context *context); 173*8975f5c5SAndroid Build Coastguard Worker angle::Result obtainNextDrawable(const gl::Context *context); 174*8975f5c5SAndroid Build Coastguard Worker angle::Result ensureCompanionTexturesSizeCorrect(const gl::Context *context); 175*8975f5c5SAndroid Build Coastguard Worker 176*8975f5c5SAndroid Build Coastguard Worker CGSize calcExpectedDrawableSize() const; 177*8975f5c5SAndroid Build Coastguard Worker // Check if metal layer has been resized. 178*8975f5c5SAndroid Build Coastguard Worker bool checkIfLayerResized(const gl::Context *context); 179*8975f5c5SAndroid Build Coastguard Worker 180*8975f5c5SAndroid Build Coastguard Worker mtl::AutoObjCObj<CAMetalLayer> mMetalLayer = nil; 181*8975f5c5SAndroid Build Coastguard Worker CALayer *mLayer; 182*8975f5c5SAndroid Build Coastguard Worker mtl::AutoObjCPtr<id<CAMetalDrawable>> mCurrentDrawable = nil; 183*8975f5c5SAndroid Build Coastguard Worker 184*8975f5c5SAndroid Build Coastguard Worker // Cache last known drawable size that is used by GL context. Can be used to detect resize 185*8975f5c5SAndroid Build Coastguard Worker // event. We don't use mMetalLayer.drawableSize directly since it might be changed internally by 186*8975f5c5SAndroid Build Coastguard Worker // metal runtime. 187*8975f5c5SAndroid Build Coastguard Worker CGSize mCurrentKnownDrawableSize; 188*8975f5c5SAndroid Build Coastguard Worker 189*8975f5c5SAndroid Build Coastguard Worker bool mRetainBuffer = false; 190*8975f5c5SAndroid Build Coastguard Worker }; 191*8975f5c5SAndroid Build Coastguard Worker 192*8975f5c5SAndroid Build Coastguard Worker // Offscreen surface, base class of PBuffer. 193*8975f5c5SAndroid Build Coastguard Worker class OffscreenSurfaceMtl : public SurfaceMtl 194*8975f5c5SAndroid Build Coastguard Worker { 195*8975f5c5SAndroid Build Coastguard Worker public: 196*8975f5c5SAndroid Build Coastguard Worker OffscreenSurfaceMtl(DisplayMtl *display, 197*8975f5c5SAndroid Build Coastguard Worker const egl::SurfaceState &state, 198*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs); 199*8975f5c5SAndroid Build Coastguard Worker ~OffscreenSurfaceMtl() override; 200*8975f5c5SAndroid Build Coastguard Worker 201*8975f5c5SAndroid Build Coastguard Worker void destroy(const egl::Display *display) override; 202*8975f5c5SAndroid Build Coastguard Worker 203*8975f5c5SAndroid Build Coastguard Worker EGLint getWidth() const override; 204*8975f5c5SAndroid Build Coastguard Worker EGLint getHeight() const override; 205*8975f5c5SAndroid Build Coastguard Worker 206*8975f5c5SAndroid Build Coastguard Worker egl::Error swap(const gl::Context *context) override; 207*8975f5c5SAndroid Build Coastguard Worker 208*8975f5c5SAndroid Build Coastguard Worker egl::Error bindTexImage(const gl::Context *context, 209*8975f5c5SAndroid Build Coastguard Worker gl::Texture *texture, 210*8975f5c5SAndroid Build Coastguard Worker EGLint buffer) override; 211*8975f5c5SAndroid Build Coastguard Worker egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; 212*8975f5c5SAndroid Build Coastguard Worker 213*8975f5c5SAndroid Build Coastguard Worker angle::Result getAttachmentRenderTarget(const gl::Context *context, 214*8975f5c5SAndroid Build Coastguard Worker GLenum binding, 215*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &imageIndex, 216*8975f5c5SAndroid Build Coastguard Worker GLsizei samples, 217*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentRenderTarget **rtOut) override; 218*8975f5c5SAndroid Build Coastguard Worker 219*8975f5c5SAndroid Build Coastguard Worker protected: 220*8975f5c5SAndroid Build Coastguard Worker angle::Result ensureTexturesSizeCorrect(const gl::Context *context); 221*8975f5c5SAndroid Build Coastguard Worker 222*8975f5c5SAndroid Build Coastguard Worker gl::Extents mSize; 223*8975f5c5SAndroid Build Coastguard Worker }; 224*8975f5c5SAndroid Build Coastguard Worker 225*8975f5c5SAndroid Build Coastguard Worker // PBuffer surface 226*8975f5c5SAndroid Build Coastguard Worker class PBufferSurfaceMtl : public OffscreenSurfaceMtl 227*8975f5c5SAndroid Build Coastguard Worker { 228*8975f5c5SAndroid Build Coastguard Worker public: 229*8975f5c5SAndroid Build Coastguard Worker PBufferSurfaceMtl(DisplayMtl *display, 230*8975f5c5SAndroid Build Coastguard Worker const egl::SurfaceState &state, 231*8975f5c5SAndroid Build Coastguard Worker const egl::AttributeMap &attribs); 232*8975f5c5SAndroid Build Coastguard Worker 233*8975f5c5SAndroid Build Coastguard Worker void setFixedWidth(EGLint width) override; 234*8975f5c5SAndroid Build Coastguard Worker void setFixedHeight(EGLint height) override; 235*8975f5c5SAndroid Build Coastguard Worker }; 236*8975f5c5SAndroid Build Coastguard Worker 237*8975f5c5SAndroid Build Coastguard Worker } // namespace rx 238*8975f5c5SAndroid Build Coastguard Worker #endif /* LIBANGLE_RENDERER_METAL_SURFACEMTL_H_ */ 239