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 // FrameBufferMtl.h: 7 // Defines the class interface for FrameBufferMtl, implementing FrameBufferImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_ 11 #define LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H_ 12 13 #import <Metal/Metal.h> 14 15 #include "libANGLE/renderer/FramebufferImpl.h" 16 #include "libANGLE/renderer/metal/RenderTargetMtl.h" 17 #include "libANGLE/renderer/metal/mtl_render_utils.h" 18 19 namespace rx 20 { 21 namespace mtl 22 { 23 class RenderCommandEncoder; 24 } // namespace mtl 25 class ContextMtl; 26 class WindowSurfaceMtl; 27 28 class FramebufferMtl : public FramebufferImpl 29 { 30 public: 31 FramebufferMtl(const gl::FramebufferState &state, bool flipY, WindowSurfaceMtl *backbuffer); 32 ~FramebufferMtl() override; 33 void destroy(const gl::Context *context) override; 34 35 angle::Result discard(const gl::Context *context, 36 size_t count, 37 const GLenum *attachments) override; 38 angle::Result invalidate(const gl::Context *context, 39 size_t count, 40 const GLenum *attachments) override; 41 angle::Result invalidateSub(const gl::Context *context, 42 size_t count, 43 const GLenum *attachments, 44 const gl::Rectangle &area) override; 45 46 angle::Result clear(const gl::Context *context, GLbitfield mask) override; 47 angle::Result clearBufferfv(const gl::Context *context, 48 GLenum buffer, 49 GLint drawbuffer, 50 const GLfloat *values) override; 51 angle::Result clearBufferuiv(const gl::Context *context, 52 GLenum buffer, 53 GLint drawbuffer, 54 const GLuint *values) override; 55 angle::Result clearBufferiv(const gl::Context *context, 56 GLenum buffer, 57 GLint drawbuffer, 58 const GLint *values) override; 59 angle::Result clearBufferfi(const gl::Context *context, 60 GLenum buffer, 61 GLint drawbuffer, 62 GLfloat depth, 63 GLint stencil) override; 64 65 const gl::InternalFormat &getImplementationColorReadFormat( 66 const gl::Context *context) const override; 67 angle::Result readPixels(const gl::Context *context, 68 const gl::Rectangle &area, 69 GLenum format, 70 GLenum type, 71 const gl::PixelPackState &pack, 72 gl::Buffer *packBuffer, 73 void *pixels) override; 74 75 angle::Result blit(const gl::Context *context, 76 const gl::Rectangle &sourceArea, 77 const gl::Rectangle &destArea, 78 GLbitfield mask, 79 GLenum filter) override; 80 81 bool checkStatus(const gl::Context *context) const override; 82 83 angle::Result syncState(const gl::Context *context, 84 GLenum binding, 85 const gl::Framebuffer::DirtyBits &dirtyBits, 86 gl::Command command) override; 87 88 angle::Result getSamplePosition(const gl::Context *context, 89 size_t index, 90 GLfloat *xy) const override; 91 92 RenderTargetMtl *getColorReadRenderTarget(const gl::Context *context) const; getDepthRenderTarget()93 RenderTargetMtl *getDepthRenderTarget() const { return mDepthRenderTarget; } getStencilRenderTarget()94 RenderTargetMtl *getStencilRenderTarget() const { return mStencilRenderTarget; } 95 flipY()96 bool flipY() const { return mFlipY; } 97 98 gl::Rectangle getCompleteRenderArea() const; 99 int getSamples() const; getAttachedBackbuffer()100 WindowSurfaceMtl *getAttachedBackbuffer() const { return mBackbuffer; } 101 102 bool renderPassHasStarted(ContextMtl *contextMtl) const; 103 mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context); 104 105 // Call this to notify FramebufferMtl whenever its render pass has started. 106 void onStartedDrawingToFrameBuffer(const gl::Context *context); 107 void onFrameEnd(const gl::Context *context); 108 109 // The actual area will be adjusted based on framebuffer flipping property. 110 gl::Rectangle getCorrectFlippedReadArea(const gl::Context *context, 111 const gl::Rectangle &glArea) const; 112 113 // NOTE: this method doesn't do the flipping of area. Caller must do it if needed before 114 // callling this. See getReadPixelsArea(). 115 angle::Result readPixelsImpl(const gl::Context *context, 116 const gl::Rectangle &area, 117 const PackPixelsParams &packPixelsParams, 118 const RenderTargetMtl *renderTarget, 119 uint8_t *pixels) const; 120 121 private: 122 void reset(); 123 bool checkPackedDepthStencilAttachment() const; 124 angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments); 125 angle::Result blitWithDraw(const gl::Context *context, 126 FramebufferMtl *srcFrameBuffer, 127 bool blitColorBuffer, 128 bool blitDepthBuffer, 129 bool blitStencilBuffer, 130 GLenum filter, 131 const mtl::BlitParams &baseParams); 132 angle::Result clearImpl(const gl::Context *context, 133 gl::DrawBufferMask clearColorBuffers, 134 mtl::ClearRectParams *clearOpts); 135 136 angle::Result clearWithLoadOp(const gl::Context *context, 137 gl::DrawBufferMask clearColorBuffers, 138 const mtl::ClearRectParams &clearOpts); 139 140 angle::Result clearWithLoadOpRenderPassNotStarted(const gl::Context *context, 141 gl::DrawBufferMask clearColorBuffers, 142 const mtl::ClearRectParams &clearOpts); 143 144 angle::Result clearWithLoadOpRenderPassStarted(const gl::Context *context, 145 gl::DrawBufferMask clearColorBuffers, 146 const mtl::ClearRectParams &clearOpts, 147 mtl::RenderCommandEncoder *encoder); 148 149 angle::Result clearWithDraw(const gl::Context *context, 150 gl::DrawBufferMask clearColorBuffers, 151 const mtl::ClearRectParams &clearOpts); 152 153 // Initialize load store options for a render pass's first start (i.e. not render pass resuming 154 // from interruptions such as those caused by a conversion compute pass) 155 void setLoadStoreActionOnRenderPassFirstStart(mtl::RenderPassAttachmentDesc *attachmentOut); 156 157 // Fill RenderPassDesc with relevant attachment's info from GL front end. 158 angle::Result prepareRenderPass(const gl::Context *context, mtl::RenderPassDesc *descOut); 159 160 // Check if a render pass specified by the given RenderPassDesc has started or not, if not this 161 // method will start the render pass and return its render encoder. 162 mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context, 163 const mtl::RenderPassDesc &desc); 164 165 angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL); 166 angle::Result updateDepthRenderTarget(const gl::Context *context); 167 angle::Result updateStencilRenderTarget(const gl::Context *context); 168 angle::Result updateCachedRenderTarget(const gl::Context *context, 169 const gl::FramebufferAttachment *attachment, 170 RenderTargetMtl **cachedRenderTarget); 171 172 angle::Result readPixelsToPBO(const gl::Context *context, 173 const gl::Rectangle &area, 174 const PackPixelsParams &packPixelsParams, 175 const RenderTargetMtl *renderTarget) const; 176 177 // NOTE: we cannot use RenderTargetCache here because it doesn't support separate 178 // depth & stencil attachments as of now. Separate depth & stencil could be useful to 179 // save spaces on iOS devices. See doc/PackedDepthStencilSupport.md. 180 std::array<RenderTargetMtl *, mtl::kMaxRenderTargets> mColorRenderTargets; 181 RenderTargetMtl *mDepthRenderTarget = nullptr; 182 RenderTargetMtl *mStencilRenderTarget = nullptr; 183 mtl::RenderPassDesc mRenderPassDesc; 184 185 const mtl::Format *mRenderPassFirstColorAttachmentFormat = nullptr; 186 bool mRenderPassAttachmentsSameColorType = false; 187 188 // Flag indicating the render pass start is a clean start or a resume from interruption such 189 // as by a compute pass. 190 bool mRenderPassCleanStart = false; 191 192 WindowSurfaceMtl *mBackbuffer = nullptr; 193 const bool mFlipY = false; 194 }; 195 } // namespace rx 196 197 #endif /* LIBANGLE_RENDERER_METAL_FRAMEBUFFERMTL_H */ 198